openssl 2.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of openssl might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/BSDL +22 -0
- data/CONTRIBUTING.md +130 -0
- data/History.md +118 -0
- data/LICENSE.txt +56 -0
- data/README.md +70 -0
- data/ext/openssl/deprecation.rb +26 -0
- data/ext/openssl/extconf.rb +158 -0
- data/ext/openssl/openssl_missing.c +173 -0
- data/ext/openssl/openssl_missing.h +244 -0
- data/ext/openssl/ossl.c +1201 -0
- data/ext/openssl/ossl.h +222 -0
- data/ext/openssl/ossl_asn1.c +1992 -0
- data/ext/openssl/ossl_asn1.h +66 -0
- data/ext/openssl/ossl_bio.c +87 -0
- data/ext/openssl/ossl_bio.h +19 -0
- data/ext/openssl/ossl_bn.c +1153 -0
- data/ext/openssl/ossl_bn.h +23 -0
- data/ext/openssl/ossl_cipher.c +1085 -0
- data/ext/openssl/ossl_cipher.h +20 -0
- data/ext/openssl/ossl_config.c +89 -0
- data/ext/openssl/ossl_config.h +19 -0
- data/ext/openssl/ossl_digest.c +453 -0
- data/ext/openssl/ossl_digest.h +20 -0
- data/ext/openssl/ossl_engine.c +580 -0
- data/ext/openssl/ossl_engine.h +19 -0
- data/ext/openssl/ossl_hmac.c +398 -0
- data/ext/openssl/ossl_hmac.h +18 -0
- data/ext/openssl/ossl_ns_spki.c +406 -0
- data/ext/openssl/ossl_ns_spki.h +19 -0
- data/ext/openssl/ossl_ocsp.c +2013 -0
- data/ext/openssl/ossl_ocsp.h +23 -0
- data/ext/openssl/ossl_pkcs12.c +259 -0
- data/ext/openssl/ossl_pkcs12.h +13 -0
- data/ext/openssl/ossl_pkcs5.c +180 -0
- data/ext/openssl/ossl_pkcs5.h +6 -0
- data/ext/openssl/ossl_pkcs7.c +1125 -0
- data/ext/openssl/ossl_pkcs7.h +20 -0
- data/ext/openssl/ossl_pkey.c +435 -0
- data/ext/openssl/ossl_pkey.h +245 -0
- data/ext/openssl/ossl_pkey_dh.c +650 -0
- data/ext/openssl/ossl_pkey_dsa.c +672 -0
- data/ext/openssl/ossl_pkey_ec.c +1899 -0
- data/ext/openssl/ossl_pkey_rsa.c +768 -0
- data/ext/openssl/ossl_rand.c +238 -0
- data/ext/openssl/ossl_rand.h +18 -0
- data/ext/openssl/ossl_ssl.c +2679 -0
- data/ext/openssl/ossl_ssl.h +41 -0
- data/ext/openssl/ossl_ssl_session.c +352 -0
- data/ext/openssl/ossl_version.h +15 -0
- data/ext/openssl/ossl_x509.c +186 -0
- data/ext/openssl/ossl_x509.h +119 -0
- data/ext/openssl/ossl_x509attr.c +328 -0
- data/ext/openssl/ossl_x509cert.c +860 -0
- data/ext/openssl/ossl_x509crl.c +565 -0
- data/ext/openssl/ossl_x509ext.c +480 -0
- data/ext/openssl/ossl_x509name.c +547 -0
- data/ext/openssl/ossl_x509req.c +492 -0
- data/ext/openssl/ossl_x509revoked.c +279 -0
- data/ext/openssl/ossl_x509store.c +846 -0
- data/ext/openssl/ruby_missing.h +32 -0
- data/lib/openssl.rb +21 -0
- data/lib/openssl/bn.rb +39 -0
- data/lib/openssl/buffering.rb +451 -0
- data/lib/openssl/cipher.rb +67 -0
- data/lib/openssl/config.rb +473 -0
- data/lib/openssl/digest.rb +78 -0
- data/lib/openssl/pkey.rb +44 -0
- data/lib/openssl/ssl.rb +416 -0
- data/lib/openssl/x509.rb +176 -0
- metadata +178 -0
@@ -0,0 +1,768 @@
|
|
1
|
+
/*
|
2
|
+
* 'OpenSSL for Ruby' project
|
3
|
+
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
4
|
+
* All rights reserved.
|
5
|
+
*/
|
6
|
+
/*
|
7
|
+
* This program is licensed under the same licence as Ruby.
|
8
|
+
* (See the file 'LICENCE'.)
|
9
|
+
*/
|
10
|
+
#include "ossl.h"
|
11
|
+
|
12
|
+
#if !defined(OPENSSL_NO_RSA)
|
13
|
+
|
14
|
+
#define GetPKeyRSA(obj, pkey) do { \
|
15
|
+
GetPKey((obj), (pkey)); \
|
16
|
+
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) { /* PARANOIA? */ \
|
17
|
+
ossl_raise(rb_eRuntimeError, "THIS IS NOT A RSA!") ; \
|
18
|
+
} \
|
19
|
+
} while (0)
|
20
|
+
#define GetRSA(obj, rsa) do { \
|
21
|
+
EVP_PKEY *_pkey; \
|
22
|
+
GetPKeyRSA((obj), _pkey); \
|
23
|
+
(rsa) = EVP_PKEY_get0_RSA(_pkey); \
|
24
|
+
} while (0)
|
25
|
+
|
26
|
+
static inline int
|
27
|
+
RSA_HAS_PRIVATE(RSA *rsa)
|
28
|
+
{
|
29
|
+
const BIGNUM *p, *q;
|
30
|
+
|
31
|
+
RSA_get0_factors(rsa, &p, &q);
|
32
|
+
return p && q; /* d? why? */
|
33
|
+
}
|
34
|
+
|
35
|
+
static inline int
|
36
|
+
RSA_PRIVATE(VALUE obj, RSA *rsa)
|
37
|
+
{
|
38
|
+
return RSA_HAS_PRIVATE(rsa) || OSSL_PKEY_IS_PRIVATE(obj);
|
39
|
+
}
|
40
|
+
|
41
|
+
/*
|
42
|
+
* Classes
|
43
|
+
*/
|
44
|
+
VALUE cRSA;
|
45
|
+
VALUE eRSAError;
|
46
|
+
|
47
|
+
/*
|
48
|
+
* Public
|
49
|
+
*/
|
50
|
+
static VALUE
|
51
|
+
rsa_instance(VALUE klass, RSA *rsa)
|
52
|
+
{
|
53
|
+
EVP_PKEY *pkey;
|
54
|
+
VALUE obj;
|
55
|
+
|
56
|
+
if (!rsa) {
|
57
|
+
return Qfalse;
|
58
|
+
}
|
59
|
+
obj = NewPKey(klass);
|
60
|
+
if (!(pkey = EVP_PKEY_new())) {
|
61
|
+
return Qfalse;
|
62
|
+
}
|
63
|
+
if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
|
64
|
+
EVP_PKEY_free(pkey);
|
65
|
+
return Qfalse;
|
66
|
+
}
|
67
|
+
SetPKey(obj, pkey);
|
68
|
+
|
69
|
+
return obj;
|
70
|
+
}
|
71
|
+
|
72
|
+
VALUE
|
73
|
+
ossl_rsa_new(EVP_PKEY *pkey)
|
74
|
+
{
|
75
|
+
VALUE obj;
|
76
|
+
|
77
|
+
if (!pkey) {
|
78
|
+
obj = rsa_instance(cRSA, RSA_new());
|
79
|
+
}
|
80
|
+
else {
|
81
|
+
obj = NewPKey(cRSA);
|
82
|
+
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) {
|
83
|
+
ossl_raise(rb_eTypeError, "Not a RSA key!");
|
84
|
+
}
|
85
|
+
SetPKey(obj, pkey);
|
86
|
+
}
|
87
|
+
if (obj == Qfalse) {
|
88
|
+
ossl_raise(eRSAError, NULL);
|
89
|
+
}
|
90
|
+
|
91
|
+
return obj;
|
92
|
+
}
|
93
|
+
|
94
|
+
/*
|
95
|
+
* Private
|
96
|
+
*/
|
97
|
+
struct rsa_blocking_gen_arg {
|
98
|
+
RSA *rsa;
|
99
|
+
BIGNUM *e;
|
100
|
+
int size;
|
101
|
+
BN_GENCB *cb;
|
102
|
+
int result;
|
103
|
+
};
|
104
|
+
|
105
|
+
static void *
|
106
|
+
rsa_blocking_gen(void *arg)
|
107
|
+
{
|
108
|
+
struct rsa_blocking_gen_arg *gen = (struct rsa_blocking_gen_arg *)arg;
|
109
|
+
gen->result = RSA_generate_key_ex(gen->rsa, gen->size, gen->e, gen->cb);
|
110
|
+
return 0;
|
111
|
+
}
|
112
|
+
|
113
|
+
static RSA *
|
114
|
+
rsa_generate(int size, unsigned long exp)
|
115
|
+
{
|
116
|
+
int i;
|
117
|
+
struct ossl_generate_cb_arg cb_arg = { 0 };
|
118
|
+
struct rsa_blocking_gen_arg gen_arg;
|
119
|
+
RSA *rsa = RSA_new();
|
120
|
+
BIGNUM *e = BN_new();
|
121
|
+
BN_GENCB *cb = BN_GENCB_new();
|
122
|
+
|
123
|
+
if (!rsa || !e || !cb) {
|
124
|
+
RSA_free(rsa);
|
125
|
+
BN_free(e);
|
126
|
+
BN_GENCB_free(cb);
|
127
|
+
return NULL;
|
128
|
+
}
|
129
|
+
for (i = 0; i < (int)sizeof(exp) * 8; ++i) {
|
130
|
+
if (exp & (1UL << i)) {
|
131
|
+
if (BN_set_bit(e, i) == 0) {
|
132
|
+
BN_free(e);
|
133
|
+
RSA_free(rsa);
|
134
|
+
BN_GENCB_free(cb);
|
135
|
+
return NULL;
|
136
|
+
}
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
if (rb_block_given_p())
|
141
|
+
cb_arg.yield = 1;
|
142
|
+
BN_GENCB_set(cb, ossl_generate_cb_2, &cb_arg);
|
143
|
+
gen_arg.rsa = rsa;
|
144
|
+
gen_arg.e = e;
|
145
|
+
gen_arg.size = size;
|
146
|
+
gen_arg.cb = cb;
|
147
|
+
if (cb_arg.yield == 1) {
|
148
|
+
/* we cannot release GVL when callback proc is supplied */
|
149
|
+
rsa_blocking_gen(&gen_arg);
|
150
|
+
} else {
|
151
|
+
/* there's a chance to unblock */
|
152
|
+
rb_thread_call_without_gvl(rsa_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg);
|
153
|
+
}
|
154
|
+
|
155
|
+
BN_GENCB_free(cb);
|
156
|
+
BN_free(e);
|
157
|
+
if (!gen_arg.result) {
|
158
|
+
RSA_free(rsa);
|
159
|
+
if (cb_arg.state) {
|
160
|
+
/* must clear OpenSSL error stack */
|
161
|
+
ossl_clear_error();
|
162
|
+
rb_jump_tag(cb_arg.state);
|
163
|
+
}
|
164
|
+
return NULL;
|
165
|
+
}
|
166
|
+
|
167
|
+
return rsa;
|
168
|
+
}
|
169
|
+
|
170
|
+
/*
|
171
|
+
* call-seq:
|
172
|
+
* RSA.generate(size) => RSA instance
|
173
|
+
* RSA.generate(size, exponent) => RSA instance
|
174
|
+
*
|
175
|
+
* Generates an RSA keypair. +size+ is an integer representing the desired key
|
176
|
+
* size. Keys smaller than 1024 should be considered insecure. +exponent+ is
|
177
|
+
* an odd number normally 3, 17, or 65537.
|
178
|
+
*/
|
179
|
+
static VALUE
|
180
|
+
ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass)
|
181
|
+
{
|
182
|
+
/* why does this method exist? why can't initialize take an optional exponent? */
|
183
|
+
RSA *rsa;
|
184
|
+
VALUE size, exp;
|
185
|
+
VALUE obj;
|
186
|
+
|
187
|
+
rb_scan_args(argc, argv, "11", &size, &exp);
|
188
|
+
|
189
|
+
rsa = rsa_generate(NUM2INT(size), NIL_P(exp) ? RSA_F4 : NUM2ULONG(exp)); /* err handled by rsa_instance */
|
190
|
+
obj = rsa_instance(klass, rsa);
|
191
|
+
|
192
|
+
if (obj == Qfalse) {
|
193
|
+
RSA_free(rsa);
|
194
|
+
ossl_raise(eRSAError, NULL);
|
195
|
+
}
|
196
|
+
|
197
|
+
return obj;
|
198
|
+
}
|
199
|
+
|
200
|
+
/*
|
201
|
+
* call-seq:
|
202
|
+
* RSA.new(key_size) => RSA instance
|
203
|
+
* RSA.new(encoded_key) => RSA instance
|
204
|
+
* RSA.new(encoded_key, pass_phrase) => RSA instance
|
205
|
+
*
|
206
|
+
* Generates or loads an RSA keypair. If an integer +key_size+ is given it
|
207
|
+
* represents the desired key size. Keys less than 1024 bits should be
|
208
|
+
* considered insecure.
|
209
|
+
*
|
210
|
+
* A key can instead be loaded from an +encoded_key+ which must be PEM or DER
|
211
|
+
* encoded. A +pass_phrase+ can be used to decrypt the key. If none is given
|
212
|
+
* OpenSSL will prompt for the pass phrase.
|
213
|
+
*
|
214
|
+
* = Examples
|
215
|
+
*
|
216
|
+
* OpenSSL::PKey::RSA.new 2048
|
217
|
+
* OpenSSL::PKey::RSA.new File.read 'rsa.pem'
|
218
|
+
* OpenSSL::PKey::RSA.new File.read('rsa.pem'), 'my pass phrase'
|
219
|
+
*/
|
220
|
+
static VALUE
|
221
|
+
ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
|
222
|
+
{
|
223
|
+
EVP_PKEY *pkey;
|
224
|
+
RSA *rsa;
|
225
|
+
BIO *in;
|
226
|
+
VALUE arg, pass;
|
227
|
+
|
228
|
+
GetPKey(self, pkey);
|
229
|
+
if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
|
230
|
+
rsa = RSA_new();
|
231
|
+
}
|
232
|
+
else if (RB_INTEGER_TYPE_P(arg)) {
|
233
|
+
rsa = rsa_generate(NUM2INT(arg), NIL_P(pass) ? RSA_F4 : NUM2ULONG(pass));
|
234
|
+
if (!rsa) ossl_raise(eRSAError, NULL);
|
235
|
+
}
|
236
|
+
else {
|
237
|
+
pass = ossl_pem_passwd_value(pass);
|
238
|
+
arg = ossl_to_der_if_possible(arg);
|
239
|
+
in = ossl_obj2bio(arg);
|
240
|
+
rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass);
|
241
|
+
if (!rsa) {
|
242
|
+
OSSL_BIO_reset(in);
|
243
|
+
rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL);
|
244
|
+
}
|
245
|
+
if (!rsa) {
|
246
|
+
OSSL_BIO_reset(in);
|
247
|
+
rsa = d2i_RSAPrivateKey_bio(in, NULL);
|
248
|
+
}
|
249
|
+
if (!rsa) {
|
250
|
+
OSSL_BIO_reset(in);
|
251
|
+
rsa = d2i_RSA_PUBKEY_bio(in, NULL);
|
252
|
+
}
|
253
|
+
if (!rsa) {
|
254
|
+
OSSL_BIO_reset(in);
|
255
|
+
rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL);
|
256
|
+
}
|
257
|
+
if (!rsa) {
|
258
|
+
OSSL_BIO_reset(in);
|
259
|
+
rsa = d2i_RSAPublicKey_bio(in, NULL);
|
260
|
+
}
|
261
|
+
BIO_free(in);
|
262
|
+
if (!rsa) {
|
263
|
+
ossl_raise(eRSAError, "Neither PUB key nor PRIV key");
|
264
|
+
}
|
265
|
+
}
|
266
|
+
if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
|
267
|
+
RSA_free(rsa);
|
268
|
+
ossl_raise(eRSAError, NULL);
|
269
|
+
}
|
270
|
+
|
271
|
+
return self;
|
272
|
+
}
|
273
|
+
|
274
|
+
static VALUE
|
275
|
+
ossl_rsa_initialize_copy(VALUE self, VALUE other)
|
276
|
+
{
|
277
|
+
EVP_PKEY *pkey;
|
278
|
+
RSA *rsa, *rsa_new;
|
279
|
+
|
280
|
+
GetPKey(self, pkey);
|
281
|
+
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
|
282
|
+
ossl_raise(eRSAError, "RSA already initialized");
|
283
|
+
GetRSA(other, rsa);
|
284
|
+
|
285
|
+
rsa_new = ASN1_dup((i2d_of_void *)i2d_RSAPrivateKey, (d2i_of_void *)d2i_RSAPrivateKey, (char *)rsa);
|
286
|
+
if (!rsa_new)
|
287
|
+
ossl_raise(eRSAError, "ASN1_dup");
|
288
|
+
|
289
|
+
EVP_PKEY_assign_RSA(pkey, rsa_new);
|
290
|
+
|
291
|
+
return self;
|
292
|
+
}
|
293
|
+
|
294
|
+
/*
|
295
|
+
* call-seq:
|
296
|
+
* rsa.public? => true
|
297
|
+
*
|
298
|
+
* The return value is always true since every private key is also a public
|
299
|
+
* key.
|
300
|
+
*/
|
301
|
+
static VALUE
|
302
|
+
ossl_rsa_is_public(VALUE self)
|
303
|
+
{
|
304
|
+
RSA *rsa;
|
305
|
+
|
306
|
+
GetRSA(self, rsa);
|
307
|
+
/*
|
308
|
+
* This method should check for n and e. BUG.
|
309
|
+
*/
|
310
|
+
(void)rsa;
|
311
|
+
return Qtrue;
|
312
|
+
}
|
313
|
+
|
314
|
+
/*
|
315
|
+
* call-seq:
|
316
|
+
* rsa.private? => true | false
|
317
|
+
*
|
318
|
+
* Does this keypair contain a private key?
|
319
|
+
*/
|
320
|
+
static VALUE
|
321
|
+
ossl_rsa_is_private(VALUE self)
|
322
|
+
{
|
323
|
+
RSA *rsa;
|
324
|
+
|
325
|
+
GetRSA(self, rsa);
|
326
|
+
|
327
|
+
return RSA_PRIVATE(self, rsa) ? Qtrue : Qfalse;
|
328
|
+
}
|
329
|
+
|
330
|
+
/*
|
331
|
+
* call-seq:
|
332
|
+
* rsa.export([cipher, pass_phrase]) => PEM-format String
|
333
|
+
* rsa.to_pem([cipher, pass_phrase]) => PEM-format String
|
334
|
+
* rsa.to_s([cipher, pass_phrase]) => PEM-format String
|
335
|
+
*
|
336
|
+
* Outputs this keypair in PEM encoding. If +cipher+ and +pass_phrase+ are
|
337
|
+
* given they will be used to encrypt the key. +cipher+ must be an
|
338
|
+
* OpenSSL::Cipher instance.
|
339
|
+
*/
|
340
|
+
static VALUE
|
341
|
+
ossl_rsa_export(int argc, VALUE *argv, VALUE self)
|
342
|
+
{
|
343
|
+
RSA *rsa;
|
344
|
+
BIO *out;
|
345
|
+
const EVP_CIPHER *ciph = NULL;
|
346
|
+
VALUE cipher, pass, str;
|
347
|
+
|
348
|
+
GetRSA(self, rsa);
|
349
|
+
|
350
|
+
rb_scan_args(argc, argv, "02", &cipher, &pass);
|
351
|
+
|
352
|
+
if (!NIL_P(cipher)) {
|
353
|
+
ciph = GetCipherPtr(cipher);
|
354
|
+
pass = ossl_pem_passwd_value(pass);
|
355
|
+
}
|
356
|
+
if (!(out = BIO_new(BIO_s_mem()))) {
|
357
|
+
ossl_raise(eRSAError, NULL);
|
358
|
+
}
|
359
|
+
if (RSA_HAS_PRIVATE(rsa)) {
|
360
|
+
if (!PEM_write_bio_RSAPrivateKey(out, rsa, ciph, NULL, 0,
|
361
|
+
ossl_pem_passwd_cb, (void *)pass)) {
|
362
|
+
BIO_free(out);
|
363
|
+
ossl_raise(eRSAError, NULL);
|
364
|
+
}
|
365
|
+
} else {
|
366
|
+
if (!PEM_write_bio_RSA_PUBKEY(out, rsa)) {
|
367
|
+
BIO_free(out);
|
368
|
+
ossl_raise(eRSAError, NULL);
|
369
|
+
}
|
370
|
+
}
|
371
|
+
str = ossl_membio2str(out);
|
372
|
+
|
373
|
+
return str;
|
374
|
+
}
|
375
|
+
|
376
|
+
/*
|
377
|
+
* call-seq:
|
378
|
+
* rsa.to_der => DER-format String
|
379
|
+
*
|
380
|
+
* Outputs this keypair in DER encoding.
|
381
|
+
*/
|
382
|
+
static VALUE
|
383
|
+
ossl_rsa_to_der(VALUE self)
|
384
|
+
{
|
385
|
+
RSA *rsa;
|
386
|
+
int (*i2d_func)(const RSA *, unsigned char **);
|
387
|
+
unsigned char *p;
|
388
|
+
long len;
|
389
|
+
VALUE str;
|
390
|
+
|
391
|
+
GetRSA(self, rsa);
|
392
|
+
if (RSA_HAS_PRIVATE(rsa))
|
393
|
+
i2d_func = i2d_RSAPrivateKey;
|
394
|
+
else
|
395
|
+
i2d_func = (int (*)(const RSA *, unsigned char **))i2d_RSA_PUBKEY;
|
396
|
+
if((len = i2d_func(rsa, NULL)) <= 0)
|
397
|
+
ossl_raise(eRSAError, NULL);
|
398
|
+
str = rb_str_new(0, len);
|
399
|
+
p = (unsigned char *)RSTRING_PTR(str);
|
400
|
+
if(i2d_func(rsa, &p) < 0)
|
401
|
+
ossl_raise(eRSAError, NULL);
|
402
|
+
ossl_str_adjust(str, p);
|
403
|
+
|
404
|
+
return str;
|
405
|
+
}
|
406
|
+
|
407
|
+
#define ossl_rsa_buf_size(rsa) (RSA_size(rsa)+16)
|
408
|
+
|
409
|
+
/*
|
410
|
+
* call-seq:
|
411
|
+
* rsa.public_encrypt(string) => String
|
412
|
+
* rsa.public_encrypt(string, padding) => String
|
413
|
+
*
|
414
|
+
* Encrypt +string+ with the public key. +padding+ defaults to PKCS1_PADDING.
|
415
|
+
* The encrypted string output can be decrypted using #private_decrypt.
|
416
|
+
*/
|
417
|
+
static VALUE
|
418
|
+
ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
|
419
|
+
{
|
420
|
+
RSA *rsa;
|
421
|
+
const BIGNUM *rsa_n;
|
422
|
+
int buf_len, pad;
|
423
|
+
VALUE str, buffer, padding;
|
424
|
+
|
425
|
+
GetRSA(self, rsa);
|
426
|
+
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
|
427
|
+
if (!rsa_n)
|
428
|
+
ossl_raise(eRSAError, "incomplete RSA");
|
429
|
+
rb_scan_args(argc, argv, "11", &buffer, &padding);
|
430
|
+
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
|
431
|
+
StringValue(buffer);
|
432
|
+
str = rb_str_new(0, ossl_rsa_buf_size(rsa));
|
433
|
+
buf_len = RSA_public_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
|
434
|
+
(unsigned char *)RSTRING_PTR(str), rsa, pad);
|
435
|
+
if (buf_len < 0) ossl_raise(eRSAError, NULL);
|
436
|
+
rb_str_set_len(str, buf_len);
|
437
|
+
|
438
|
+
return str;
|
439
|
+
}
|
440
|
+
|
441
|
+
/*
|
442
|
+
* call-seq:
|
443
|
+
* rsa.public_decrypt(string) => String
|
444
|
+
* rsa.public_decrypt(string, padding) => String
|
445
|
+
*
|
446
|
+
* Decrypt +string+, which has been encrypted with the private key, with the
|
447
|
+
* public key. +padding+ defaults to PKCS1_PADDING.
|
448
|
+
*/
|
449
|
+
static VALUE
|
450
|
+
ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
|
451
|
+
{
|
452
|
+
RSA *rsa;
|
453
|
+
const BIGNUM *rsa_n;
|
454
|
+
int buf_len, pad;
|
455
|
+
VALUE str, buffer, padding;
|
456
|
+
|
457
|
+
GetRSA(self, rsa);
|
458
|
+
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
|
459
|
+
if (!rsa_n)
|
460
|
+
ossl_raise(eRSAError, "incomplete RSA");
|
461
|
+
rb_scan_args(argc, argv, "11", &buffer, &padding);
|
462
|
+
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
|
463
|
+
StringValue(buffer);
|
464
|
+
str = rb_str_new(0, ossl_rsa_buf_size(rsa));
|
465
|
+
buf_len = RSA_public_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
|
466
|
+
(unsigned char *)RSTRING_PTR(str), rsa, pad);
|
467
|
+
if (buf_len < 0) ossl_raise(eRSAError, NULL);
|
468
|
+
rb_str_set_len(str, buf_len);
|
469
|
+
|
470
|
+
return str;
|
471
|
+
}
|
472
|
+
|
473
|
+
/*
|
474
|
+
* call-seq:
|
475
|
+
* rsa.private_encrypt(string) => String
|
476
|
+
* rsa.private_encrypt(string, padding) => String
|
477
|
+
*
|
478
|
+
* Encrypt +string+ with the private key. +padding+ defaults to PKCS1_PADDING.
|
479
|
+
* The encrypted string output can be decrypted using #public_decrypt.
|
480
|
+
*/
|
481
|
+
static VALUE
|
482
|
+
ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
|
483
|
+
{
|
484
|
+
RSA *rsa;
|
485
|
+
const BIGNUM *rsa_n;
|
486
|
+
int buf_len, pad;
|
487
|
+
VALUE str, buffer, padding;
|
488
|
+
|
489
|
+
GetRSA(self, rsa);
|
490
|
+
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
|
491
|
+
if (!rsa_n)
|
492
|
+
ossl_raise(eRSAError, "incomplete RSA");
|
493
|
+
if (!RSA_PRIVATE(self, rsa))
|
494
|
+
ossl_raise(eRSAError, "private key needed.");
|
495
|
+
rb_scan_args(argc, argv, "11", &buffer, &padding);
|
496
|
+
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
|
497
|
+
StringValue(buffer);
|
498
|
+
str = rb_str_new(0, ossl_rsa_buf_size(rsa));
|
499
|
+
buf_len = RSA_private_encrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
|
500
|
+
(unsigned char *)RSTRING_PTR(str), rsa, pad);
|
501
|
+
if (buf_len < 0) ossl_raise(eRSAError, NULL);
|
502
|
+
rb_str_set_len(str, buf_len);
|
503
|
+
|
504
|
+
return str;
|
505
|
+
}
|
506
|
+
|
507
|
+
/*
|
508
|
+
* call-seq:
|
509
|
+
* rsa.private_decrypt(string) => String
|
510
|
+
* rsa.private_decrypt(string, padding) => String
|
511
|
+
*
|
512
|
+
* Decrypt +string+, which has been encrypted with the public key, with the
|
513
|
+
* private key. +padding+ defaults to PKCS1_PADDING.
|
514
|
+
*/
|
515
|
+
static VALUE
|
516
|
+
ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
|
517
|
+
{
|
518
|
+
RSA *rsa;
|
519
|
+
const BIGNUM *rsa_n;
|
520
|
+
int buf_len, pad;
|
521
|
+
VALUE str, buffer, padding;
|
522
|
+
|
523
|
+
GetRSA(self, rsa);
|
524
|
+
RSA_get0_key(rsa, &rsa_n, NULL, NULL);
|
525
|
+
if (!rsa_n)
|
526
|
+
ossl_raise(eRSAError, "incomplete RSA");
|
527
|
+
if (!RSA_PRIVATE(self, rsa))
|
528
|
+
ossl_raise(eRSAError, "private key needed.");
|
529
|
+
rb_scan_args(argc, argv, "11", &buffer, &padding);
|
530
|
+
pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
|
531
|
+
StringValue(buffer);
|
532
|
+
str = rb_str_new(0, ossl_rsa_buf_size(rsa));
|
533
|
+
buf_len = RSA_private_decrypt(RSTRING_LENINT(buffer), (unsigned char *)RSTRING_PTR(buffer),
|
534
|
+
(unsigned char *)RSTRING_PTR(str), rsa, pad);
|
535
|
+
if (buf_len < 0) ossl_raise(eRSAError, NULL);
|
536
|
+
rb_str_set_len(str, buf_len);
|
537
|
+
|
538
|
+
return str;
|
539
|
+
}
|
540
|
+
|
541
|
+
/*
|
542
|
+
* call-seq:
|
543
|
+
* rsa.params => hash
|
544
|
+
*
|
545
|
+
* THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!!
|
546
|
+
*
|
547
|
+
* Stores all parameters of key to the hash. The hash has keys 'n', 'e', 'd',
|
548
|
+
* 'p', 'q', 'dmp1', 'dmq1', 'iqmp'.
|
549
|
+
*
|
550
|
+
* Don't use :-)) (It's up to you)
|
551
|
+
*/
|
552
|
+
static VALUE
|
553
|
+
ossl_rsa_get_params(VALUE self)
|
554
|
+
{
|
555
|
+
RSA *rsa;
|
556
|
+
VALUE hash;
|
557
|
+
const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
|
558
|
+
|
559
|
+
GetRSA(self, rsa);
|
560
|
+
RSA_get0_key(rsa, &n, &e, &d);
|
561
|
+
RSA_get0_factors(rsa, &p, &q);
|
562
|
+
RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
|
563
|
+
|
564
|
+
hash = rb_hash_new();
|
565
|
+
rb_hash_aset(hash, rb_str_new2("n"), ossl_bn_new(n));
|
566
|
+
rb_hash_aset(hash, rb_str_new2("e"), ossl_bn_new(e));
|
567
|
+
rb_hash_aset(hash, rb_str_new2("d"), ossl_bn_new(d));
|
568
|
+
rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p));
|
569
|
+
rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q));
|
570
|
+
rb_hash_aset(hash, rb_str_new2("dmp1"), ossl_bn_new(dmp1));
|
571
|
+
rb_hash_aset(hash, rb_str_new2("dmq1"), ossl_bn_new(dmq1));
|
572
|
+
rb_hash_aset(hash, rb_str_new2("iqmp"), ossl_bn_new(iqmp));
|
573
|
+
|
574
|
+
return hash;
|
575
|
+
}
|
576
|
+
|
577
|
+
/*
|
578
|
+
* call-seq:
|
579
|
+
* rsa.to_text => String
|
580
|
+
*
|
581
|
+
* THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!!
|
582
|
+
*
|
583
|
+
* Dumps all parameters of a keypair to a String
|
584
|
+
*
|
585
|
+
* Don't use :-)) (It's up to you)
|
586
|
+
*/
|
587
|
+
static VALUE
|
588
|
+
ossl_rsa_to_text(VALUE self)
|
589
|
+
{
|
590
|
+
RSA *rsa;
|
591
|
+
BIO *out;
|
592
|
+
VALUE str;
|
593
|
+
|
594
|
+
GetRSA(self, rsa);
|
595
|
+
if (!(out = BIO_new(BIO_s_mem()))) {
|
596
|
+
ossl_raise(eRSAError, NULL);
|
597
|
+
}
|
598
|
+
if (!RSA_print(out, rsa, 0)) { /* offset = 0 */
|
599
|
+
BIO_free(out);
|
600
|
+
ossl_raise(eRSAError, NULL);
|
601
|
+
}
|
602
|
+
str = ossl_membio2str(out);
|
603
|
+
|
604
|
+
return str;
|
605
|
+
}
|
606
|
+
|
607
|
+
/*
|
608
|
+
* call-seq:
|
609
|
+
* rsa.public_key -> RSA
|
610
|
+
*
|
611
|
+
* Makes new RSA instance containing the public key from the private key.
|
612
|
+
*/
|
613
|
+
static VALUE
|
614
|
+
ossl_rsa_to_public_key(VALUE self)
|
615
|
+
{
|
616
|
+
EVP_PKEY *pkey;
|
617
|
+
RSA *rsa;
|
618
|
+
VALUE obj;
|
619
|
+
|
620
|
+
GetPKeyRSA(self, pkey);
|
621
|
+
/* err check performed by rsa_instance */
|
622
|
+
rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(pkey));
|
623
|
+
obj = rsa_instance(CLASS_OF(self), rsa);
|
624
|
+
if (obj == Qfalse) {
|
625
|
+
RSA_free(rsa);
|
626
|
+
ossl_raise(eRSAError, NULL);
|
627
|
+
}
|
628
|
+
return obj;
|
629
|
+
}
|
630
|
+
|
631
|
+
/*
|
632
|
+
* TODO: Test me
|
633
|
+
|
634
|
+
static VALUE
|
635
|
+
ossl_rsa_blinding_on(VALUE self)
|
636
|
+
{
|
637
|
+
RSA *rsa;
|
638
|
+
|
639
|
+
GetRSA(self, rsa);
|
640
|
+
|
641
|
+
if (RSA_blinding_on(rsa, ossl_bn_ctx) != 1) {
|
642
|
+
ossl_raise(eRSAError, NULL);
|
643
|
+
}
|
644
|
+
return self;
|
645
|
+
}
|
646
|
+
|
647
|
+
static VALUE
|
648
|
+
ossl_rsa_blinding_off(VALUE self)
|
649
|
+
{
|
650
|
+
RSA *rsa;
|
651
|
+
|
652
|
+
GetRSA(self, rsa);
|
653
|
+
RSA_blinding_off(rsa);
|
654
|
+
|
655
|
+
return self;
|
656
|
+
}
|
657
|
+
*/
|
658
|
+
|
659
|
+
/*
|
660
|
+
* Document-method: OpenSSL::PKey::RSA#set_key
|
661
|
+
* call-seq:
|
662
|
+
* rsa.set_key(n, e, d) -> self
|
663
|
+
*
|
664
|
+
* Sets +n+, +e+, +d+ for the RSA instance.
|
665
|
+
*/
|
666
|
+
OSSL_PKEY_BN_DEF3(rsa, RSA, key, n, e, d)
|
667
|
+
/*
|
668
|
+
* Document-method: OpenSSL::PKey::RSA#set_factors
|
669
|
+
* call-seq:
|
670
|
+
* rsa.set_factors(p, q) -> self
|
671
|
+
*
|
672
|
+
* Sets +p+, +q+ for the RSA instance.
|
673
|
+
*/
|
674
|
+
OSSL_PKEY_BN_DEF2(rsa, RSA, factors, p, q)
|
675
|
+
/*
|
676
|
+
* Document-method: OpenSSL::PKey::RSA#set_crt_params
|
677
|
+
* call-seq:
|
678
|
+
* rsa.set_crt_params(dmp1, dmq1, iqmp) -> self
|
679
|
+
*
|
680
|
+
* Sets +dmp1+, +dmq1+, +iqmp+ for the RSA instance. They are calculated by
|
681
|
+
* <tt>d mod (p - 1)</tt>, <tt>d mod (q - 1)</tt> and <tt>q^(-1) mod p</tt>
|
682
|
+
* respectively.
|
683
|
+
*/
|
684
|
+
OSSL_PKEY_BN_DEF3(rsa, RSA, crt_params, dmp1, dmq1, iqmp)
|
685
|
+
|
686
|
+
/*
|
687
|
+
* INIT
|
688
|
+
*/
|
689
|
+
#define DefRSAConst(x) rb_define_const(cRSA, #x, INT2NUM(RSA_##x))
|
690
|
+
|
691
|
+
void
|
692
|
+
Init_ossl_rsa(void)
|
693
|
+
{
|
694
|
+
#if 0
|
695
|
+
mPKey = rb_define_module_under(mOSSL, "PKey");
|
696
|
+
cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
|
697
|
+
ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
|
698
|
+
#endif
|
699
|
+
|
700
|
+
/* Document-class: OpenSSL::PKey::RSAError
|
701
|
+
*
|
702
|
+
* Generic exception that is raised if an operation on an RSA PKey
|
703
|
+
* fails unexpectedly or in case an instantiation of an instance of RSA
|
704
|
+
* fails due to non-conformant input data.
|
705
|
+
*/
|
706
|
+
eRSAError = rb_define_class_under(mPKey, "RSAError", ePKeyError);
|
707
|
+
|
708
|
+
/* Document-class: OpenSSL::PKey::RSA
|
709
|
+
*
|
710
|
+
* RSA is an asymmetric public key algorithm that has been formalized in
|
711
|
+
* RFC 3447. It is in widespread use in public key infrastuctures (PKI)
|
712
|
+
* where certificates (cf. OpenSSL::X509::Certificate) often are issued
|
713
|
+
* on the basis of a public/private RSA key pair. RSA is used in a wide
|
714
|
+
* field of applications such as secure (symmetric) key exchange, e.g.
|
715
|
+
* when establishing a secure TLS/SSL connection. It is also used in
|
716
|
+
* various digital signature schemes.
|
717
|
+
*/
|
718
|
+
cRSA = rb_define_class_under(mPKey, "RSA", cPKey);
|
719
|
+
|
720
|
+
rb_define_singleton_method(cRSA, "generate", ossl_rsa_s_generate, -1);
|
721
|
+
rb_define_method(cRSA, "initialize", ossl_rsa_initialize, -1);
|
722
|
+
rb_define_copy_func(cRSA, ossl_rsa_initialize_copy);
|
723
|
+
|
724
|
+
rb_define_method(cRSA, "public?", ossl_rsa_is_public, 0);
|
725
|
+
rb_define_method(cRSA, "private?", ossl_rsa_is_private, 0);
|
726
|
+
rb_define_method(cRSA, "to_text", ossl_rsa_to_text, 0);
|
727
|
+
rb_define_method(cRSA, "export", ossl_rsa_export, -1);
|
728
|
+
rb_define_alias(cRSA, "to_pem", "export");
|
729
|
+
rb_define_alias(cRSA, "to_s", "export");
|
730
|
+
rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0);
|
731
|
+
rb_define_method(cRSA, "public_key", ossl_rsa_to_public_key, 0);
|
732
|
+
rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, -1);
|
733
|
+
rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1);
|
734
|
+
rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1);
|
735
|
+
rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, -1);
|
736
|
+
|
737
|
+
DEF_OSSL_PKEY_BN(cRSA, rsa, n);
|
738
|
+
DEF_OSSL_PKEY_BN(cRSA, rsa, e);
|
739
|
+
DEF_OSSL_PKEY_BN(cRSA, rsa, d);
|
740
|
+
DEF_OSSL_PKEY_BN(cRSA, rsa, p);
|
741
|
+
DEF_OSSL_PKEY_BN(cRSA, rsa, q);
|
742
|
+
DEF_OSSL_PKEY_BN(cRSA, rsa, dmp1);
|
743
|
+
DEF_OSSL_PKEY_BN(cRSA, rsa, dmq1);
|
744
|
+
DEF_OSSL_PKEY_BN(cRSA, rsa, iqmp);
|
745
|
+
rb_define_method(cRSA, "set_key", ossl_rsa_set_key, 3);
|
746
|
+
rb_define_method(cRSA, "set_factors", ossl_rsa_set_factors, 2);
|
747
|
+
rb_define_method(cRSA, "set_crt_params", ossl_rsa_set_crt_params, 3);
|
748
|
+
|
749
|
+
rb_define_method(cRSA, "params", ossl_rsa_get_params, 0);
|
750
|
+
|
751
|
+
DefRSAConst(PKCS1_PADDING);
|
752
|
+
DefRSAConst(SSLV23_PADDING);
|
753
|
+
DefRSAConst(NO_PADDING);
|
754
|
+
DefRSAConst(PKCS1_OAEP_PADDING);
|
755
|
+
|
756
|
+
/*
|
757
|
+
* TODO: Test it
|
758
|
+
rb_define_method(cRSA, "blinding_on!", ossl_rsa_blinding_on, 0);
|
759
|
+
rb_define_method(cRSA, "blinding_off!", ossl_rsa_blinding_off, 0);
|
760
|
+
*/
|
761
|
+
}
|
762
|
+
|
763
|
+
#else /* defined NO_RSA */
|
764
|
+
void
|
765
|
+
Init_ossl_rsa(void)
|
766
|
+
{
|
767
|
+
}
|
768
|
+
#endif /* NO_RSA */
|