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.

Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/BSDL +22 -0
  3. data/CONTRIBUTING.md +130 -0
  4. data/History.md +118 -0
  5. data/LICENSE.txt +56 -0
  6. data/README.md +70 -0
  7. data/ext/openssl/deprecation.rb +26 -0
  8. data/ext/openssl/extconf.rb +158 -0
  9. data/ext/openssl/openssl_missing.c +173 -0
  10. data/ext/openssl/openssl_missing.h +244 -0
  11. data/ext/openssl/ossl.c +1201 -0
  12. data/ext/openssl/ossl.h +222 -0
  13. data/ext/openssl/ossl_asn1.c +1992 -0
  14. data/ext/openssl/ossl_asn1.h +66 -0
  15. data/ext/openssl/ossl_bio.c +87 -0
  16. data/ext/openssl/ossl_bio.h +19 -0
  17. data/ext/openssl/ossl_bn.c +1153 -0
  18. data/ext/openssl/ossl_bn.h +23 -0
  19. data/ext/openssl/ossl_cipher.c +1085 -0
  20. data/ext/openssl/ossl_cipher.h +20 -0
  21. data/ext/openssl/ossl_config.c +89 -0
  22. data/ext/openssl/ossl_config.h +19 -0
  23. data/ext/openssl/ossl_digest.c +453 -0
  24. data/ext/openssl/ossl_digest.h +20 -0
  25. data/ext/openssl/ossl_engine.c +580 -0
  26. data/ext/openssl/ossl_engine.h +19 -0
  27. data/ext/openssl/ossl_hmac.c +398 -0
  28. data/ext/openssl/ossl_hmac.h +18 -0
  29. data/ext/openssl/ossl_ns_spki.c +406 -0
  30. data/ext/openssl/ossl_ns_spki.h +19 -0
  31. data/ext/openssl/ossl_ocsp.c +2013 -0
  32. data/ext/openssl/ossl_ocsp.h +23 -0
  33. data/ext/openssl/ossl_pkcs12.c +259 -0
  34. data/ext/openssl/ossl_pkcs12.h +13 -0
  35. data/ext/openssl/ossl_pkcs5.c +180 -0
  36. data/ext/openssl/ossl_pkcs5.h +6 -0
  37. data/ext/openssl/ossl_pkcs7.c +1125 -0
  38. data/ext/openssl/ossl_pkcs7.h +20 -0
  39. data/ext/openssl/ossl_pkey.c +435 -0
  40. data/ext/openssl/ossl_pkey.h +245 -0
  41. data/ext/openssl/ossl_pkey_dh.c +650 -0
  42. data/ext/openssl/ossl_pkey_dsa.c +672 -0
  43. data/ext/openssl/ossl_pkey_ec.c +1899 -0
  44. data/ext/openssl/ossl_pkey_rsa.c +768 -0
  45. data/ext/openssl/ossl_rand.c +238 -0
  46. data/ext/openssl/ossl_rand.h +18 -0
  47. data/ext/openssl/ossl_ssl.c +2679 -0
  48. data/ext/openssl/ossl_ssl.h +41 -0
  49. data/ext/openssl/ossl_ssl_session.c +352 -0
  50. data/ext/openssl/ossl_version.h +15 -0
  51. data/ext/openssl/ossl_x509.c +186 -0
  52. data/ext/openssl/ossl_x509.h +119 -0
  53. data/ext/openssl/ossl_x509attr.c +328 -0
  54. data/ext/openssl/ossl_x509cert.c +860 -0
  55. data/ext/openssl/ossl_x509crl.c +565 -0
  56. data/ext/openssl/ossl_x509ext.c +480 -0
  57. data/ext/openssl/ossl_x509name.c +547 -0
  58. data/ext/openssl/ossl_x509req.c +492 -0
  59. data/ext/openssl/ossl_x509revoked.c +279 -0
  60. data/ext/openssl/ossl_x509store.c +846 -0
  61. data/ext/openssl/ruby_missing.h +32 -0
  62. data/lib/openssl.rb +21 -0
  63. data/lib/openssl/bn.rb +39 -0
  64. data/lib/openssl/buffering.rb +451 -0
  65. data/lib/openssl/cipher.rb +67 -0
  66. data/lib/openssl/config.rb +473 -0
  67. data/lib/openssl/digest.rb +78 -0
  68. data/lib/openssl/pkey.rb +44 -0
  69. data/lib/openssl/ssl.rb +416 -0
  70. data/lib/openssl/x509.rb +176 -0
  71. 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 */