rubysl-openssl 1.0.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -6
  3. data/ext/rubysl/openssl/.gitignore +3 -0
  4. data/ext/rubysl/openssl/deprecation.rb +21 -0
  5. data/ext/rubysl/openssl/extconf.rb +45 -32
  6. data/ext/rubysl/openssl/openssl_missing.c +20 -7
  7. data/ext/rubysl/openssl/openssl_missing.h +22 -15
  8. data/ext/rubysl/openssl/ossl.c +610 -61
  9. data/ext/rubysl/openssl/ossl.h +31 -17
  10. data/ext/rubysl/openssl/ossl_asn1.c +974 -183
  11. data/ext/rubysl/openssl/ossl_asn1.h +3 -3
  12. data/ext/rubysl/openssl/ossl_bio.c +4 -3
  13. data/ext/rubysl/openssl/ossl_bio.h +1 -1
  14. data/ext/rubysl/openssl/ossl_bn.c +32 -28
  15. data/ext/rubysl/openssl/ossl_bn.h +1 -1
  16. data/ext/rubysl/openssl/ossl_cipher.c +494 -93
  17. data/ext/rubysl/openssl/ossl_cipher.h +1 -1
  18. data/ext/rubysl/openssl/ossl_config.c +4 -5
  19. data/ext/rubysl/openssl/ossl_config.h +1 -1
  20. data/ext/rubysl/openssl/ossl_digest.c +206 -24
  21. data/ext/rubysl/openssl/ossl_digest.h +1 -1
  22. data/ext/rubysl/openssl/ossl_engine.c +48 -26
  23. data/ext/rubysl/openssl/ossl_engine.h +1 -1
  24. data/ext/rubysl/openssl/ossl_hmac.c +40 -38
  25. data/ext/rubysl/openssl/ossl_hmac.h +1 -1
  26. data/ext/rubysl/openssl/ossl_ns_spki.c +157 -25
  27. data/ext/rubysl/openssl/ossl_ns_spki.h +1 -1
  28. data/ext/rubysl/openssl/ossl_ocsp.c +57 -40
  29. data/ext/rubysl/openssl/ossl_ocsp.h +1 -1
  30. data/ext/rubysl/openssl/ossl_pkcs12.c +15 -13
  31. data/ext/rubysl/openssl/ossl_pkcs12.h +1 -1
  32. data/ext/rubysl/openssl/ossl_pkcs5.c +108 -18
  33. data/ext/rubysl/openssl/ossl_pkcs7.c +44 -37
  34. data/ext/rubysl/openssl/ossl_pkcs7.h +1 -1
  35. data/ext/rubysl/openssl/ossl_pkey.c +211 -15
  36. data/ext/rubysl/openssl/ossl_pkey.h +19 -9
  37. data/ext/rubysl/openssl/ossl_pkey_dh.c +180 -47
  38. data/ext/rubysl/openssl/ossl_pkey_dsa.c +184 -47
  39. data/ext/rubysl/openssl/ossl_pkey_ec.c +177 -93
  40. data/ext/rubysl/openssl/ossl_pkey_rsa.c +209 -102
  41. data/ext/rubysl/openssl/ossl_rand.c +15 -15
  42. data/ext/rubysl/openssl/ossl_rand.h +1 -1
  43. data/ext/rubysl/openssl/ossl_ssl.c +939 -192
  44. data/ext/rubysl/openssl/ossl_ssl.h +6 -6
  45. data/ext/rubysl/openssl/ossl_ssl_session.c +78 -62
  46. data/ext/rubysl/openssl/ossl_version.h +2 -2
  47. data/ext/rubysl/openssl/ossl_x509.c +1 -1
  48. data/ext/rubysl/openssl/ossl_x509.h +1 -1
  49. data/ext/rubysl/openssl/ossl_x509attr.c +20 -19
  50. data/ext/rubysl/openssl/ossl_x509cert.c +169 -67
  51. data/ext/rubysl/openssl/ossl_x509crl.c +41 -39
  52. data/ext/rubysl/openssl/ossl_x509ext.c +51 -38
  53. data/ext/rubysl/openssl/ossl_x509name.c +139 -29
  54. data/ext/rubysl/openssl/ossl_x509req.c +42 -40
  55. data/ext/rubysl/openssl/ossl_x509revoked.c +20 -20
  56. data/ext/rubysl/openssl/ossl_x509store.c +99 -47
  57. data/ext/rubysl/openssl/ruby_missing.h +3 -16
  58. data/lib/openssl/bn.rb +19 -19
  59. data/lib/openssl/buffering.rb +222 -14
  60. data/lib/openssl/cipher.rb +20 -20
  61. data/lib/openssl/config.rb +1 -4
  62. data/lib/openssl/digest.rb +47 -19
  63. data/lib/openssl/ssl.rb +197 -1
  64. data/lib/openssl/x509.rb +162 -1
  65. data/lib/rubysl/openssl.rb +4 -8
  66. data/lib/rubysl/openssl/version.rb +1 -1
  67. data/rubysl-openssl.gemspec +1 -2
  68. metadata +16 -34
  69. data/ext/rubysl/openssl/extconf.h +0 -50
  70. data/lib/openssl/net/ftptls.rb +0 -53
  71. data/lib/openssl/net/telnets.rb +0 -251
  72. data/lib/openssl/pkcs7.rb +0 -25
  73. data/lib/openssl/ssl-internal.rb +0 -187
  74. data/lib/openssl/x509-internal.rb +0 -153
@@ -1,5 +1,5 @@
1
1
  /*
2
- * $Id: ossl_pkey_dsa.c 28004 2010-05-24 23:58:49Z shyouhei $
2
+ * $Id$
3
3
  * 'OpenSSL for Ruby' project
4
4
  * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
5
5
  * All rights reserved.
@@ -13,8 +13,8 @@
13
13
  #include "ossl.h"
14
14
 
15
15
  #define GetPKeyDSA(obj, pkey) do { \
16
- GetPKey(obj, pkey); \
17
- if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DSA) { /* PARANOIA? */ \
16
+ GetPKey((obj), (pkey)); \
17
+ if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_DSA) { /* PARANOIA? */ \
18
18
  ossl_raise(rb_eRuntimeError, "THIS IS NOT A DSA!"); \
19
19
  } \
20
20
  } while (0)
@@ -36,7 +36,7 @@ dsa_instance(VALUE klass, DSA *dsa)
36
36
  {
37
37
  EVP_PKEY *pkey;
38
38
  VALUE obj;
39
-
39
+
40
40
  if (!dsa) {
41
41
  return Qfalse;
42
42
  }
@@ -75,9 +75,69 @@ ossl_dsa_new(EVP_PKEY *pkey)
75
75
  /*
76
76
  * Private
77
77
  */
78
+ #if defined(HAVE_DSA_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB
79
+ struct dsa_blocking_gen_arg {
80
+ DSA *dsa;
81
+ int size;
82
+ unsigned char* seed;
83
+ int seed_len;
84
+ int *counter;
85
+ unsigned long *h;
86
+ BN_GENCB *cb;
87
+ int result;
88
+ };
89
+
90
+ static void *
91
+ dsa_blocking_gen(void *arg)
92
+ {
93
+ struct dsa_blocking_gen_arg *gen = (struct dsa_blocking_gen_arg *)arg;
94
+ gen->result = DSA_generate_parameters_ex(gen->dsa, gen->size, gen->seed, gen->seed_len, gen->counter, gen->h, gen->cb);
95
+ return 0;
96
+ }
97
+ #endif
98
+
78
99
  static DSA *
79
100
  dsa_generate(int size)
80
101
  {
102
+ #if defined(HAVE_DSA_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB
103
+ BN_GENCB cb;
104
+ struct ossl_generate_cb_arg cb_arg;
105
+ struct dsa_blocking_gen_arg gen_arg;
106
+ DSA *dsa = DSA_new();
107
+ unsigned char seed[20];
108
+ int seed_len = 20, counter;
109
+ unsigned long h;
110
+
111
+ if (!dsa) return 0;
112
+ if (!RAND_bytes(seed, seed_len)) {
113
+ DSA_free(dsa);
114
+ return 0;
115
+ }
116
+
117
+ memset(&cb_arg, 0, sizeof(struct ossl_generate_cb_arg));
118
+ if (rb_block_given_p())
119
+ cb_arg.yield = 1;
120
+ BN_GENCB_set(&cb, ossl_generate_cb_2, &cb_arg);
121
+ gen_arg.dsa = dsa;
122
+ gen_arg.size = size;
123
+ gen_arg.seed = seed;
124
+ gen_arg.seed_len = seed_len;
125
+ gen_arg.counter = &counter;
126
+ gen_arg.h = &h;
127
+ gen_arg.cb = &cb;
128
+ if (cb_arg.yield == 1) {
129
+ /* we cannot release GVL when callback proc is supplied */
130
+ dsa_blocking_gen(&gen_arg);
131
+ } else {
132
+ /* there's a chance to unblock */
133
+ rb_thread_call_without_gvl(dsa_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg);
134
+ }
135
+ if (!gen_arg.result) {
136
+ DSA_free(dsa);
137
+ if (cb_arg.state) rb_jump_tag(cb_arg.state);
138
+ return 0;
139
+ }
140
+ #else
81
141
  DSA *dsa;
82
142
  unsigned char seed[20];
83
143
  int seed_len = 20, counter;
@@ -87,9 +147,9 @@ dsa_generate(int size)
87
147
  return 0;
88
148
  }
89
149
  dsa = DSA_generate_parameters(size, seed, seed_len, &counter, &h,
90
- rb_block_given_p() ? ossl_generate_cb : NULL,
91
- NULL);
150
+ rb_block_given_p() ? ossl_generate_cb : NULL, NULL);
92
151
  if(!dsa) return 0;
152
+ #endif
93
153
 
94
154
  if (!DSA_generate_key(dsa)) {
95
155
  DSA_free(dsa);
@@ -103,8 +163,11 @@ dsa_generate(int size)
103
163
  * call-seq:
104
164
  * DSA.generate(size) -> dsa
105
165
  *
106
- * === Parameters
107
- * * +size+ is an integer representing the desired key size.
166
+ * Creates a new DSA instance by generating a private/public key pair
167
+ * from scratch.
168
+ *
169
+ * === Parameters
170
+ * * +size+ is an integer representing the desired key size.
108
171
  *
109
172
  */
110
173
  static VALUE
@@ -125,16 +188,18 @@ ossl_dsa_s_generate(VALUE klass, VALUE size)
125
188
  * call-seq:
126
189
  * DSA.new([size | string [, pass]) -> dsa
127
190
  *
128
- * === Parameters
129
- * * +size+ is an integer representing the desired key size.
130
- * * +string+ contains a DER or PEM encoded key.
131
- * * +pass+ is a string that contains a optional password.
191
+ * Creates a new DSA instance by reading an existing key from +string+.
132
192
  *
133
- * === Examples
134
- * * DSA.new -> dsa
135
- * * DSA.new(1024) -> dsa
136
- * * DSA.new(File.read('dsa.pem')) -> dsa
137
- * * DSA.new(File.read('dsa.pem'), 'mypassword') -> dsa
193
+ * === Parameters
194
+ * * +size+ is an integer representing the desired key size.
195
+ * * +string+ contains a DER or PEM encoded key.
196
+ * * +pass+ is a string that contains an optional password.
197
+ *
198
+ * === Examples
199
+ * DSA.new -> dsa
200
+ * DSA.new(1024) -> dsa
201
+ * DSA.new(File.read('dsa.pem')) -> dsa
202
+ * DSA.new(File.read('dsa.pem'), 'mypassword') -> dsa
138
203
  *
139
204
  */
140
205
  static VALUE
@@ -145,7 +210,7 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
145
210
  BIO *in;
146
211
  char *passwd = NULL;
147
212
  VALUE arg, pass;
148
-
213
+
149
214
  GetPKey(self, pkey);
150
215
  if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
151
216
  dsa = DSA_new();
@@ -161,23 +226,26 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
161
226
  in = ossl_obj2bio(arg);
162
227
  dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
163
228
  if (!dsa) {
164
- BIO_reset(in);
165
- dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL);
166
- }
167
- if (!dsa) {
168
- BIO_reset(in);
229
+ OSSL_BIO_reset(in);
169
230
  dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL);
170
231
  }
171
232
  if (!dsa) {
172
- BIO_reset(in);
233
+ OSSL_BIO_reset(in);
173
234
  dsa = d2i_DSAPrivateKey_bio(in, NULL);
174
235
  }
175
236
  if (!dsa) {
176
- BIO_reset(in);
237
+ OSSL_BIO_reset(in);
177
238
  dsa = d2i_DSA_PUBKEY_bio(in, NULL);
178
239
  }
240
+ if (!dsa) {
241
+ OSSL_BIO_reset(in);
242
+ dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL);
243
+ }
179
244
  BIO_free(in);
180
- if (!dsa) ossl_raise(eDSAError, "Neither PUB key nor PRIV key:");
245
+ if (!dsa) {
246
+ ERR_clear_error();
247
+ ossl_raise(eDSAError, "Neither PUB key nor PRIV key");
248
+ }
181
249
  }
182
250
  if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
183
251
  DSA_free(dsa);
@@ -191,6 +259,8 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
191
259
  * call-seq:
192
260
  * dsa.public? -> true | false
193
261
  *
262
+ * Indicates whether this DSA instance has a public key associated with it or
263
+ * not. The public key may be retrieved with DSA#public_key.
194
264
  */
195
265
  static VALUE
196
266
  ossl_dsa_is_public(VALUE self)
@@ -206,14 +276,16 @@ ossl_dsa_is_public(VALUE self)
206
276
  * call-seq:
207
277
  * dsa.private? -> true | false
208
278
  *
279
+ * Indicates whether this DSA instance has a private key associated with it or
280
+ * not. The private key may be retrieved with DSA#private_key.
209
281
  */
210
282
  static VALUE
211
283
  ossl_dsa_is_private(VALUE self)
212
284
  {
213
285
  EVP_PKEY *pkey;
214
-
286
+
215
287
  GetPKeyDSA(self, pkey);
216
-
288
+
217
289
  return (DSA_PRIVATE(self, pkey->pkey.dsa)) ? Qtrue : Qfalse;
218
290
  }
219
291
 
@@ -221,13 +293,15 @@ ossl_dsa_is_private(VALUE self)
221
293
  * call-seq:
222
294
  * dsa.to_pem([cipher, password]) -> aString
223
295
  *
224
- * === Parameters
225
- * +cipher+ is an OpenSSL::Cipher.
226
- * +password+ is a string containing your password.
296
+ * Encodes this DSA to its PEM encoding.
227
297
  *
228
- * === Examples
229
- * * DSA.to_pem -> aString
230
- * * DSA.to_pem(cipher, 'mypassword') -> aString
298
+ * === Parameters
299
+ * * +cipher+ is an OpenSSL::Cipher.
300
+ * * +password+ is a string containing your password.
301
+ *
302
+ * === Examples
303
+ * DSA.to_pem -> aString
304
+ * DSA.to_pem(cipher, 'mypassword') -> aString
231
305
  *
232
306
  */
233
307
  static VALUE
@@ -244,7 +318,10 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self)
244
318
  if (!NIL_P(cipher)) {
245
319
  ciph = GetCipherPtr(cipher);
246
320
  if (!NIL_P(pass)) {
247
- passwd = StringValuePtr(pass);
321
+ StringValue(pass);
322
+ if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN)
323
+ ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long");
324
+ passwd = RSTRING_PTR(pass);
248
325
  }
249
326
  }
250
327
  if (!(out = BIO_new(BIO_s_mem()))) {
@@ -257,7 +334,7 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self)
257
334
  ossl_raise(eDSAError, NULL);
258
335
  }
259
336
  } else {
260
- if (!PEM_write_bio_DSAPublicKey(out, pkey->pkey.dsa)) {
337
+ if (!PEM_write_bio_DSA_PUBKEY(out, pkey->pkey.dsa)) {
261
338
  BIO_free(out);
262
339
  ossl_raise(eDSAError, NULL);
263
340
  }
@@ -271,6 +348,8 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self)
271
348
  * call-seq:
272
349
  * dsa.to_der -> aString
273
350
  *
351
+ * Encodes this DSA to its DER encoding.
352
+ *
274
353
  */
275
354
  static VALUE
276
355
  ossl_dsa_to_der(VALUE self)
@@ -289,7 +368,7 @@ ossl_dsa_to_der(VALUE self)
289
368
  if((len = i2d_func(pkey->pkey.dsa, NULL)) <= 0)
290
369
  ossl_raise(eDSAError, NULL);
291
370
  str = rb_str_new(0, len);
292
- p = RSTRING_PTR(str);
371
+ p = (unsigned char *)RSTRING_PTR(str);
293
372
  if(i2d_func(pkey->pkey.dsa, &p) < 0)
294
373
  ossl_raise(eDSAError, NULL);
295
374
  ossl_str_adjust(str, p);
@@ -320,7 +399,7 @@ ossl_dsa_get_params(VALUE self)
320
399
  rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dsa->g));
321
400
  rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dsa->pub_key));
322
401
  rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dsa->priv_key));
323
-
402
+
324
403
  return hash;
325
404
  }
326
405
 
@@ -356,7 +435,18 @@ ossl_dsa_to_text(VALUE self)
356
435
  * call-seq:
357
436
  * dsa.public_key -> aDSA
358
437
  *
359
- * Makes new instance DSA PUBLIC_KEY from PRIVATE_KEY
438
+ * Returns a new DSA instance that carries just the public key information.
439
+ * If the current instance has also private key information, this will no
440
+ * longer be present in the new instance. This feature is helpful for
441
+ * publishing the public key information without leaking any of the private
442
+ * information.
443
+ *
444
+ * === Example
445
+ * dsa = OpenSSL::PKey::DSA.new(2048) # has public and private information
446
+ * pub_key = dsa.public_key # has only the public part available
447
+ * pub_key_der = pub_key.to_der # it's safe to publish this
448
+ *
449
+ *
360
450
  */
361
451
  static VALUE
362
452
  ossl_dsa_to_public_key(VALUE self)
@@ -364,7 +454,7 @@ ossl_dsa_to_public_key(VALUE self)
364
454
  EVP_PKEY *pkey;
365
455
  DSA *dsa;
366
456
  VALUE obj;
367
-
457
+
368
458
  GetPKeyDSA(self, pkey);
369
459
  /* err check performed by dsa_instance */
370
460
  dsa = DSAPublicKey_dup(pkey->pkey.dsa);
@@ -382,12 +472,26 @@ ossl_dsa_to_public_key(VALUE self)
382
472
  * call-seq:
383
473
  * dsa.syssign(string) -> aString
384
474
  *
475
+ * Computes and returns the DSA signature of +string+, where +string+ is
476
+ * expected to be an already-computed message digest of the original input
477
+ * data. The signature is issued using the private key of this DSA instance.
478
+ *
479
+ * === Parameters
480
+ * * +string+ is a message digest of the original input data to be signed
481
+ *
482
+ * === Example
483
+ * dsa = OpenSSL::PKey::DSA.new(2048)
484
+ * doc = "Sign me"
485
+ * digest = OpenSSL::Digest::SHA1.digest(doc)
486
+ * sig = dsa.syssign(digest)
487
+ *
488
+ *
385
489
  */
386
490
  static VALUE
387
491
  ossl_dsa_sign(VALUE self, VALUE data)
388
492
  {
389
493
  EVP_PKEY *pkey;
390
- int buf_len;
494
+ unsigned int buf_len;
391
495
  VALUE str;
392
496
 
393
497
  GetPKeyDSA(self, pkey);
@@ -396,7 +500,8 @@ ossl_dsa_sign(VALUE self, VALUE data)
396
500
  ossl_raise(eDSAError, "Private DSA key needed!");
397
501
  }
398
502
  str = rb_str_new(0, ossl_dsa_buf_size(pkey));
399
- if (!DSA_sign(0, RSTRING_PTR(data), RSTRING_LEN(data), RSTRING_PTR(str),
503
+ if (!DSA_sign(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
504
+ (unsigned char *)RSTRING_PTR(str),
400
505
  &buf_len, pkey->pkey.dsa)) { /* type is ignored (0) */
401
506
  ossl_raise(eDSAError, NULL);
402
507
  }
@@ -409,6 +514,20 @@ ossl_dsa_sign(VALUE self, VALUE data)
409
514
  * call-seq:
410
515
  * dsa.sysverify(digest, sig) -> true | false
411
516
  *
517
+ * Verifies whether the signature is valid given the message digest input. It
518
+ * does so by validating +sig+ using the public key of this DSA instance.
519
+ *
520
+ * === Parameters
521
+ * * +digest+ is a message digest of the original input data to be signed
522
+ * * +sig+ is a DSA signature value
523
+ *
524
+ * === Example
525
+ * dsa = OpenSSL::PKey::DSA.new(2048)
526
+ * doc = "Sign me"
527
+ * digest = OpenSSL::Digest::SHA1.digest(doc)
528
+ * sig = dsa.syssign(digest)
529
+ * puts dsa.sysverify(digest, sig) # => true
530
+ *
412
531
  */
413
532
  static VALUE
414
533
  ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
@@ -420,8 +539,8 @@ ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
420
539
  StringValue(digest);
421
540
  StringValue(sig);
422
541
  /* type is ignored (0) */
423
- ret = DSA_verify(0, RSTRING_PTR(digest), RSTRING_LEN(digest),
424
- RSTRING_PTR(sig), RSTRING_LEN(sig), pkey->pkey.dsa);
542
+ ret = DSA_verify(0, (unsigned char *)RSTRING_PTR(digest), RSTRING_LENINT(digest),
543
+ (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), pkey->pkey.dsa);
425
544
  if (ret < 0) {
426
545
  ossl_raise(eDSAError, NULL);
427
546
  }
@@ -444,15 +563,33 @@ OSSL_PKEY_BN(dsa, priv_key)
444
563
  void
445
564
  Init_ossl_dsa()
446
565
  {
447
- #if 0 /* let rdoc know about mOSSL and mPKey */
448
- mOSSL = rb_define_module("OpenSSL");
566
+ #if 0
567
+ mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */
449
568
  mPKey = rb_define_module_under(mOSSL, "PKey");
450
569
  #endif
451
570
 
571
+ /* Document-class: OpenSSL::PKey::DSAError
572
+ *
573
+ * Generic exception that is raised if an operation on a DSA PKey
574
+ * fails unexpectedly or in case an instantiation of an instance of DSA
575
+ * fails due to non-conformant input data.
576
+ */
452
577
  eDSAError = rb_define_class_under(mPKey, "DSAError", ePKeyError);
453
578
 
579
+ /* Document-class: OpenSSL::PKey::DSA
580
+ *
581
+ * DSA, the Digital Signature Algorithm, is specified in NIST's
582
+ * FIPS 186-3. It is an asymmetric public key algorithm that may be used
583
+ * similar to e.g. RSA.
584
+ * Please note that for OpenSSL versions prior to 1.0.0 the digest
585
+ * algorithms OpenSSL::Digest::DSS (equivalent to SHA) or
586
+ * OpenSSL::Digest::DSS1 (equivalent to SHA-1) must be used for issuing
587
+ * signatures with a DSA key using OpenSSL::PKey#sign.
588
+ * Starting with OpenSSL 1.0.0, digest algorithms are no longer restricted,
589
+ * any Digest may be used for signing.
590
+ */
454
591
  cDSA = rb_define_class_under(mPKey, "DSA", cPKey);
455
-
592
+
456
593
  rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1);
457
594
  rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1);
458
595
 
@@ -22,70 +22,70 @@ typedef struct {
22
22
 
23
23
 
24
24
  #define GetPKeyEC(obj, pkey) do { \
25
- GetPKey(obj, pkey); \
26
- if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) { \
25
+ GetPKey((obj), (pkey)); \
26
+ if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_EC) { \
27
27
  ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \
28
28
  } \
29
29
  } while (0)
30
30
 
31
31
  #define SafeGet_ec_group(obj, group) do { \
32
- OSSL_Check_Kind(obj, cEC_GROUP); \
33
- Data_Get_Struct(obj, ossl_ec_group, group); \
32
+ OSSL_Check_Kind((obj), cEC_GROUP); \
33
+ Data_Get_Struct((obj), ossl_ec_group, (group)); \
34
34
  } while(0)
35
35
 
36
36
  #define Get_EC_KEY(obj, key) do { \
37
37
  EVP_PKEY *pkey; \
38
- GetPKeyEC(obj, pkey); \
39
- key = pkey->pkey.ec; \
38
+ GetPKeyEC((obj), pkey); \
39
+ (key) = pkey->pkey.ec; \
40
40
  } while(0)
41
41
 
42
42
  #define Require_EC_KEY(obj, key) do { \
43
- Get_EC_KEY(obj, key); \
44
- if (key == NULL) \
45
- rb_raise(eECError, "EC_KEY is not initialized"); \
43
+ Get_EC_KEY((obj), (key)); \
44
+ if ((key) == NULL) \
45
+ ossl_raise(eECError, "EC_KEY is not initialized"); \
46
46
  } while(0)
47
47
 
48
48
  #define SafeRequire_EC_KEY(obj, key) do { \
49
- OSSL_Check_Kind(obj, cEC); \
50
- Require_EC_KEY(obj, key); \
49
+ OSSL_Check_Kind((obj), cEC); \
50
+ Require_EC_KEY((obj), (key)); \
51
51
  } while (0)
52
52
 
53
53
  #define Get_EC_GROUP(obj, g) do { \
54
54
  ossl_ec_group *ec_group; \
55
- Data_Get_Struct(obj, ossl_ec_group, ec_group); \
55
+ Data_Get_Struct((obj), ossl_ec_group, ec_group); \
56
56
  if (ec_group == NULL) \
57
- rb_raise(eEC_GROUP, "missing ossl_ec_group structure"); \
58
- g = ec_group->group; \
57
+ ossl_raise(eEC_GROUP, "missing ossl_ec_group structure"); \
58
+ (g) = ec_group->group; \
59
59
  } while(0)
60
60
 
61
61
  #define Require_EC_GROUP(obj, group) do { \
62
- Get_EC_GROUP(obj, group); \
63
- if (group == NULL) \
64
- rb_raise(eEC_GROUP, "EC_GROUP is not initialized"); \
62
+ Get_EC_GROUP((obj), (group)); \
63
+ if ((group) == NULL) \
64
+ ossl_raise(eEC_GROUP, "EC_GROUP is not initialized"); \
65
65
  } while(0)
66
66
 
67
67
  #define SafeRequire_EC_GROUP(obj, group) do { \
68
- OSSL_Check_Kind(obj, cEC_GROUP); \
69
- Require_EC_GROUP(obj, group); \
68
+ OSSL_Check_Kind((obj), cEC_GROUP); \
69
+ Require_EC_GROUP((obj), (group)); \
70
70
  } while(0)
71
71
 
72
72
  #define Get_EC_POINT(obj, p) do { \
73
73
  ossl_ec_point *ec_point; \
74
- Data_Get_Struct(obj, ossl_ec_point, ec_point); \
74
+ Data_Get_Struct((obj), ossl_ec_point, ec_point); \
75
75
  if (ec_point == NULL) \
76
- rb_raise(eEC_POINT, "missing ossl_ec_point structure"); \
77
- p = ec_point->point; \
76
+ ossl_raise(eEC_POINT, "missing ossl_ec_point structure"); \
77
+ (p) = ec_point->point; \
78
78
  } while(0)
79
79
 
80
80
  #define Require_EC_POINT(obj, point) do { \
81
- Get_EC_POINT(obj, point); \
82
- if (point == NULL) \
83
- rb_raise(eEC_POINT, "EC_POINT is not initialized"); \
81
+ Get_EC_POINT((obj), (point)); \
82
+ if ((point) == NULL) \
83
+ ossl_raise(eEC_POINT, "EC_POINT is not initialized"); \
84
84
  } while(0)
85
85
 
86
86
  #define SafeRequire_EC_POINT(obj, point) do { \
87
- OSSL_Check_Kind(obj, cEC_POINT); \
88
- Require_EC_POINT(obj, point); \
87
+ OSSL_Check_Kind((obj), cEC_POINT); \
88
+ Require_EC_POINT((obj), (point)); \
89
89
  } while(0)
90
90
 
91
91
  VALUE cEC;
@@ -110,7 +110,7 @@ static VALUE ec_instance(VALUE klass, EC_KEY *ec)
110
110
  {
111
111
  EVP_PKEY *pkey;
112
112
  VALUE obj;
113
-
113
+
114
114
  if (!ec) {
115
115
  return Qfalse;
116
116
  }
@@ -152,6 +152,7 @@ VALUE ossl_ec_new(EVP_PKEY *pkey)
152
152
  * OpenSSL::PKey::EC.new(ec_group)
153
153
  * OpenSSL::PKey::EC.new("secp112r1")
154
154
  * OpenSSL::PKey::EC.new(pem_string)
155
+ * OpenSSL::PKey::EC.new(pem_string [, pwd])
155
156
  * OpenSSL::PKey::EC.new(der_string)
156
157
  *
157
158
  * See the OpenSSL documentation for:
@@ -163,10 +164,11 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
163
164
  EC_KEY *ec = NULL;
164
165
  VALUE arg, pass;
165
166
  VALUE group = Qnil;
166
-
167
+ char *passwd = NULL;
168
+
167
169
  GetPKey(self, pkey);
168
170
  if (pkey->pkey.ec)
169
- rb_raise(eECError, "EC_KEY already initialized");
171
+ ossl_raise(eECError, "EC_KEY already initialized");
170
172
 
171
173
  rb_scan_args(argc, argv, "02", &arg, &pass);
172
174
 
@@ -184,26 +186,30 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
184
186
  } else {
185
187
  BIO *in = ossl_obj2bio(arg);
186
188
 
187
- ec = PEM_read_bio_ECPrivateKey(in, NULL, NULL, NULL);
189
+ if (!NIL_P(pass)) {
190
+ passwd = StringValuePtr(pass);
191
+ }
192
+ ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
188
193
  if (!ec) {
189
- BIO_reset(in);
190
- ec = PEM_read_bio_EC_PUBKEY(in, NULL, NULL, NULL);
194
+ OSSL_BIO_reset(in);
195
+ ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, passwd);
191
196
  }
192
197
  if (!ec) {
193
- BIO_reset(in);
198
+ OSSL_BIO_reset(in);
194
199
  ec = d2i_ECPrivateKey_bio(in, NULL);
195
200
  }
196
201
  if (!ec) {
197
- BIO_reset(in);
202
+ OSSL_BIO_reset(in);
198
203
  ec = d2i_EC_PUBKEY_bio(in, NULL);
199
204
  }
200
205
 
201
206
  BIO_free(in);
202
207
 
203
208
  if (ec == NULL) {
204
- const char *name = STR2CSTR(arg);
209
+ const char *name = StringValueCStr(arg);
205
210
  int nid = OBJ_sn2nid(name);
206
211
 
212
+ (void)ERR_get_error();
207
213
  if (nid == NID_undef)
208
214
  ossl_raise(eECError, "unknown curve name (%s)\n", name);
209
215
 
@@ -274,7 +280,7 @@ static VALUE ossl_ec_key_get_group(VALUE self)
274
280
  * the group.
275
281
  *
276
282
  * Setting the group will immediately destroy any previously assigned group object.
277
- * The group is internally copied by OpenSSL. Modifying the original group after
283
+ * The group is internally copied by OpenSSL. Modifying the original group after
278
284
  * assignment will not effect the internal key structure.
279
285
  * (your changes may be lost). BE CAREFUL.
280
286
  *
@@ -457,22 +463,19 @@ static VALUE ossl_ec_key_is_private_key(VALUE self)
457
463
  return (EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse);
458
464
  }
459
465
 
460
- static VALUE ossl_ec_key_to_string(VALUE self, int format)
466
+ static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int format)
461
467
  {
462
468
  EC_KEY *ec;
463
469
  BIO *out;
464
470
  int i = -1;
465
471
  int private = 0;
466
- #if 0 /* unused now */
467
- EVP_CIPHER *cipher = NULL;
468
472
  char *password = NULL;
469
- #endif
470
473
  VALUE str;
471
474
 
472
475
  Require_EC_KEY(self, ec);
473
476
 
474
477
  if (EC_KEY_get0_public_key(ec) == NULL)
475
- rb_raise(eECError, "can't export - no public key set");
478
+ ossl_raise(eECError, "can't export - no public key set");
476
479
 
477
480
  if (EC_KEY_check_key(ec) != 1)
478
481
  ossl_raise(eECError, "can't export - EC_KEY_check_key failed");
@@ -486,44 +489,36 @@ static VALUE ossl_ec_key_to_string(VALUE self, int format)
486
489
  switch(format) {
487
490
  case EXPORT_PEM:
488
491
  if (private) {
489
- #if 0 /* unused now */
490
- if (cipher || password)
491
- /* BUG: finish cipher/password key export */
492
- rb_notimplement();
492
+ const EVP_CIPHER *cipher;
493
+ if (!NIL_P(ciph)) {
494
+ cipher = GetCipherPtr(ciph);
495
+ if (!NIL_P(pass)) {
496
+ StringValue(pass);
497
+ if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN)
498
+ ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long");
499
+ password = RSTRING_PTR(pass);
500
+ }
501
+ }
502
+ else {
503
+ cipher = NULL;
504
+ }
493
505
  i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, NULL, password);
494
- #endif
495
- i = PEM_write_bio_ECPrivateKey(out, ec, NULL, NULL, 0, NULL, NULL);
496
506
  } else {
497
- #if 0 /* unused now */
498
- if (cipher || password)
499
- rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
500
- #endif
501
-
502
507
  i = PEM_write_bio_EC_PUBKEY(out, ec);
503
508
  }
504
509
 
505
510
  break;
506
511
  case EXPORT_DER:
507
512
  if (private) {
508
- #if 0 /* unused now */
509
- if (cipher || password)
510
- rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
511
- #endif
512
-
513
513
  i = i2d_ECPrivateKey_bio(out, ec);
514
514
  } else {
515
- #if 0 /* unused now */
516
- if (cipher || password)
517
- rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
518
- #endif
519
-
520
515
  i = i2d_EC_PUBKEY_bio(out, ec);
521
516
  }
522
517
 
523
518
  break;
524
519
  default:
525
520
  BIO_free(out);
526
- rb_raise(rb_eRuntimeError, "unknown format (internal error)");
521
+ ossl_raise(rb_eRuntimeError, "unknown format (internal error)");
527
522
  }
528
523
 
529
524
  if (i != 1) {
@@ -538,13 +533,21 @@ static VALUE ossl_ec_key_to_string(VALUE self, int format)
538
533
 
539
534
  /*
540
535
  * call-seq:
541
- * key.to_pem => String
536
+ * key.export => String
537
+ * key.export(cipher, pass_phrase) => String
538
+ *
539
+ * Outputs the EC key in PEM encoding. If +cipher+ and +pass_phrase+ are
540
+ * given they will be used to encrypt the key. +cipher+ must be an
541
+ * OpenSSL::Cipher::Cipher instance. Note that encryption will only be
542
+ * effective for a private key, public keys will always be encoded in plain
543
+ * text.
542
544
  *
543
- * See the OpenSSL documentation for PEM_write_bio_ECPrivateKey()
544
545
  */
545
- static VALUE ossl_ec_key_to_pem(VALUE self)
546
+ static VALUE ossl_ec_key_export(int argc, VALUE *argv, VALUE self)
546
547
  {
547
- return ossl_ec_key_to_string(self, EXPORT_PEM);
548
+ VALUE cipher, passwd;
549
+ rb_scan_args(argc, argv, "02", &cipher, &passwd);
550
+ return ossl_ec_key_to_string(self, cipher, passwd, EXPORT_PEM);
548
551
  }
549
552
 
550
553
  /*
@@ -555,7 +558,7 @@ static VALUE ossl_ec_key_to_pem(VALUE self)
555
558
  */
556
559
  static VALUE ossl_ec_key_to_der(VALUE self)
557
560
  {
558
- return ossl_ec_key_to_string(self, EXPORT_DER);
561
+ return ossl_ec_key_to_string(self, Qnil, Qnil, EXPORT_DER);
559
562
  }
560
563
 
561
564
  /*
@@ -671,7 +674,7 @@ static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data)
671
674
  ossl_raise(eECError, "Private EC key needed!");
672
675
 
673
676
  str = rb_str_new(0, ECDSA_size(ec) + 16);
674
- if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LEN(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1)
677
+ if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1)
675
678
  ossl_raise(eECError, "ECDSA_sign");
676
679
 
677
680
  rb_str_resize(str, buf_len);
@@ -693,13 +696,15 @@ static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
693
696
  StringValue(data);
694
697
  StringValue(sig);
695
698
 
696
- switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LEN(data), (unsigned char *) RSTRING_PTR(sig), RSTRING_LEN(sig), ec)) {
699
+ switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(sig), (int)RSTRING_LEN(sig), ec)) {
697
700
  case 1: return Qtrue;
698
701
  case 0: return Qfalse;
699
702
  default: break;
700
703
  }
701
704
 
702
705
  ossl_raise(eECError, "ECDSA_verify");
706
+
707
+ UNREACHABLE;
703
708
  }
704
709
 
705
710
  static void ossl_ec_group_free(ossl_ec_group *ec_group)
@@ -743,7 +748,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
743
748
 
744
749
  Data_Get_Struct(self, ossl_ec_group, ec_group);
745
750
  if (ec_group->group != NULL)
746
- rb_raise(rb_eRuntimeError, "EC_GROUP is already initialized");
751
+ ossl_raise(rb_eRuntimeError, "EC_GROUP is already initialized");
747
752
 
748
753
  switch (rb_scan_args(argc, argv, "13", &arg1, &arg2, &arg3, &arg4)) {
749
754
  case 1:
@@ -765,7 +770,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
765
770
  if ((group = EC_GROUP_new(method)) == NULL)
766
771
  ossl_raise(eEC_GROUP, "EC_GROUP_new");
767
772
  } else {
768
- rb_raise(rb_eArgError, "unknown symbol, must be :GFp_simple, :GFp_mont, :GFp_nist or :GF2m_simple");
773
+ ossl_raise(rb_eArgError, "unknown symbol, must be :GFp_simple, :GFp_mont, :GFp_nist or :GF2m_simple");
769
774
  }
770
775
  } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
771
776
  const EC_GROUP *arg1_group;
@@ -778,16 +783,17 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
778
783
 
779
784
  group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
780
785
  if (!group) {
781
- BIO_reset(in);
786
+ OSSL_BIO_reset(in);
782
787
  group = d2i_ECPKParameters_bio(in, NULL);
783
788
  }
784
789
 
785
790
  BIO_free(in);
786
791
 
787
792
  if (!group) {
788
- const char *name = STR2CSTR(arg1);
793
+ const char *name = StringValueCStr(arg1);
789
794
  int nid = OBJ_sn2nid(name);
790
795
 
796
+ (void)ERR_get_error();
791
797
  if (nid == NID_undef)
792
798
  ossl_raise(eEC_GROUP, "unknown curve name (%s)", name);
793
799
 
@@ -814,18 +820,18 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
814
820
  } else if (id == s_GF2m) {
815
821
  new_curve = EC_GROUP_new_curve_GF2m;
816
822
  } else {
817
- rb_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m");
823
+ ossl_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m");
818
824
  }
819
825
 
820
826
  if ((group = new_curve(p, a, b, ossl_bn_ctx)) == NULL)
821
827
  ossl_raise(eEC_GROUP, "EC_GROUP_new_by_GF*");
822
828
  } else {
823
- rb_raise(rb_eArgError, "unknown argument, must be :GFp or :GF2m");
829
+ ossl_raise(rb_eArgError, "unknown argument, must be :GFp or :GF2m");
824
830
  }
825
831
 
826
832
  break;
827
833
  default:
828
- rb_raise(rb_eArgError, "wrong number of arguments");
834
+ ossl_raise(rb_eArgError, "wrong number of arguments");
829
835
  }
830
836
 
831
837
  if (group == NULL)
@@ -965,7 +971,7 @@ static VALUE ossl_s_builtin_curves(VALUE self)
965
971
  {
966
972
  EC_builtin_curve *curves = NULL;
967
973
  int n;
968
- int crv_len = EC_get_builtin_curves(NULL, 0);
974
+ int crv_len = rb_long2int(EC_get_builtin_curves(NULL, 0));
969
975
  VALUE ary, ret;
970
976
 
971
977
  curves = ALLOCA_N(EC_builtin_curve, crv_len);
@@ -1023,7 +1029,7 @@ static VALUE ossl_ec_group_set_asn1_flag(VALUE self, VALUE flag_v)
1023
1029
  }
1024
1030
 
1025
1031
  /* call-seq:
1026
- * group.point_conversion_form => :uncompressed | :compressed | :hybrid
1032
+ * group.point_conversion_form => :uncompressed | :compressed | :hybrid
1027
1033
  *
1028
1034
  * See the OpenSSL documentation for EC_GROUP_get_point_conversion_form()
1029
1035
  */
@@ -1041,9 +1047,9 @@ static VALUE ossl_ec_group_get_point_conversion_form(VALUE self)
1041
1047
  case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed; break;
1042
1048
  case POINT_CONVERSION_COMPRESSED: ret = ID_compressed; break;
1043
1049
  case POINT_CONVERSION_HYBRID: ret = ID_hybrid; break;
1044
- default: rb_raise(eEC_GROUP, "unsupported point conversion form: %d, this module should be updated", form);
1050
+ default: ossl_raise(eEC_GROUP, "unsupported point conversion form: %d, this module should be updated", form);
1045
1051
  }
1046
-
1052
+
1047
1053
  return ID2SYM(ret);
1048
1054
  }
1049
1055
 
@@ -1067,7 +1073,7 @@ static VALUE ossl_ec_group_set_point_conversion_form(VALUE self, VALUE form_v)
1067
1073
  } else if (form_id == ID_hybrid) {
1068
1074
  form = POINT_CONVERSION_HYBRID;
1069
1075
  } else {
1070
- rb_raise(rb_eArgError, "form must be :compressed, :uncompressed, or :hybrid");
1076
+ ossl_raise(rb_eArgError, "form must be :compressed, :uncompressed, or :hybrid");
1071
1077
  }
1072
1078
 
1073
1079
  EC_GROUP_set_point_conversion_form(group, form);
@@ -1092,7 +1098,7 @@ static VALUE ossl_ec_group_get_seed(VALUE self)
1092
1098
  if (seed_len == 0)
1093
1099
  return Qnil;
1094
1100
 
1095
- return rb_str_new(EC_GROUP_get0_seed(group), seed_len);
1101
+ return rb_str_new((const char *)EC_GROUP_get0_seed(group), seed_len);
1096
1102
  }
1097
1103
 
1098
1104
  /* call-seq:
@@ -1107,7 +1113,7 @@ static VALUE ossl_ec_group_set_seed(VALUE self, VALUE seed)
1107
1113
  Require_EC_GROUP(self, group);
1108
1114
  StringValue(seed);
1109
1115
 
1110
- if (EC_GROUP_set_seed(group, RSTRING_PTR(seed), RSTRING_LEN(seed)) != RSTRING_LEN(seed))
1116
+ if (EC_GROUP_set_seed(group, (unsigned char *)RSTRING_PTR(seed), RSTRING_LEN(seed)) != (size_t)RSTRING_LEN(seed))
1111
1117
  ossl_raise(eEC_GROUP, "EC_GROUP_set_seed");
1112
1118
 
1113
1119
  return seed;
@@ -1150,7 +1156,7 @@ static VALUE ossl_ec_group_to_string(VALUE self, int format)
1150
1156
  break;
1151
1157
  default:
1152
1158
  BIO_free(out);
1153
- rb_raise(rb_eRuntimeError, "unknown format (internal error)");
1159
+ ossl_raise(rb_eRuntimeError, "unknown format (internal error)");
1154
1160
  }
1155
1161
 
1156
1162
  if (i != 1) {
@@ -1243,7 +1249,7 @@ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
1243
1249
 
1244
1250
  Data_Get_Struct(self, ossl_ec_point, ec_point);
1245
1251
  if (ec_point->point)
1246
- rb_raise(eEC_POINT, "EC_POINT already initialized");
1252
+ ossl_raise(eEC_POINT, "EC_POINT already initialized");
1247
1253
 
1248
1254
  switch (rb_scan_args(argc, argv, "11", &arg1, &arg2)) {
1249
1255
  case 1:
@@ -1261,16 +1267,16 @@ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
1261
1267
 
1262
1268
  point = EC_POINT_new(group);
1263
1269
  } else {
1264
- rb_raise(eEC_POINT, "wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
1270
+ ossl_raise(eEC_POINT, "wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
1265
1271
  }
1266
1272
 
1267
1273
  break;
1268
1274
  case 2:
1269
1275
  if (!rb_obj_is_kind_of(arg1, cEC_GROUP))
1270
- rb_raise(rb_eArgError, "1st argument must be OpenSSL::PKey::EC::Group");
1276
+ ossl_raise(rb_eArgError, "1st argument must be OpenSSL::PKey::EC::Group");
1271
1277
  group_v = arg1;
1272
1278
  SafeRequire_EC_GROUP(group_v, group);
1273
-
1279
+
1274
1280
  if (rb_obj_is_kind_of(arg2, cBN)) {
1275
1281
  const BIGNUM *bn = GetBNPtr(arg2);
1276
1282
 
@@ -1288,14 +1294,14 @@ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
1288
1294
  }
1289
1295
  break;
1290
1296
  default:
1291
- rb_raise(rb_eArgError, "wrong number of arguments");
1297
+ ossl_raise(rb_eArgError, "wrong number of arguments");
1292
1298
  }
1293
1299
 
1294
1300
  if (point == NULL)
1295
1301
  ossl_raise(eEC_POINT, NULL);
1296
1302
 
1297
1303
  if (NIL_P(group_v))
1298
- rb_raise(rb_eRuntimeError, "missing group (internal error)");
1304
+ ossl_raise(rb_eRuntimeError, "missing group (internal error)");
1299
1305
 
1300
1306
  ec_point->point = point;
1301
1307
 
@@ -1348,6 +1354,8 @@ static VALUE ossl_ec_point_is_at_infinity(VALUE self)
1348
1354
  case 0: return Qfalse;
1349
1355
  default: ossl_raise(cEC_POINT, "EC_POINT_is_at_infinity");
1350
1356
  }
1357
+
1358
+ UNREACHABLE;
1351
1359
  }
1352
1360
 
1353
1361
  /*
@@ -1369,6 +1377,8 @@ static VALUE ossl_ec_point_is_on_curve(VALUE self)
1369
1377
  case 0: return Qfalse;
1370
1378
  default: ossl_raise(cEC_POINT, "EC_POINT_is_on_curve");
1371
1379
  }
1380
+
1381
+ UNREACHABLE;
1372
1382
  }
1373
1383
 
1374
1384
  /*
@@ -1460,6 +1470,78 @@ static VALUE ossl_ec_point_to_bn(VALUE self)
1460
1470
  return bn_obj;
1461
1471
  }
1462
1472
 
1473
+ /*
1474
+ * call-seq:
1475
+ * point.mul(bn) => point
1476
+ * point.mul(bn, bn) => point
1477
+ * point.mul([bn], [point]) => point
1478
+ * point.mul([bn], [point], bn) => point
1479
+ */
1480
+ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
1481
+ {
1482
+ EC_POINT *point1, *point2;
1483
+ const EC_GROUP *group;
1484
+ VALUE group_v = rb_iv_get(self, "@group");
1485
+ VALUE bn_v1, bn_v2, r, points_v;
1486
+ BIGNUM *bn1 = NULL, *bn2 = NULL;
1487
+
1488
+ Require_EC_POINT(self, point1);
1489
+ SafeRequire_EC_GROUP(group_v, group);
1490
+
1491
+ r = rb_obj_alloc(cEC_POINT);
1492
+ ossl_ec_point_initialize(1, &group_v, r);
1493
+ Require_EC_POINT(r, point2);
1494
+
1495
+ argc = rb_scan_args(argc, argv, "12", &bn_v1, &points_v, &bn_v2);
1496
+
1497
+ if (rb_obj_is_kind_of(bn_v1, cBN)) {
1498
+ bn1 = GetBNPtr(bn_v1);
1499
+ if (argc >= 2) {
1500
+ bn2 = GetBNPtr(points_v);
1501
+ }
1502
+ if (EC_POINT_mul(group, point2, bn2, point1, bn1, ossl_bn_ctx) != 1)
1503
+ ossl_raise(eEC_POINT, "Multiplication failed");
1504
+ } else {
1505
+ size_t i, points_len, bignums_len;
1506
+ const EC_POINT **points;
1507
+ const BIGNUM **bignums;
1508
+
1509
+ Check_Type(bn_v1, T_ARRAY);
1510
+ bignums_len = RARRAY_LEN(bn_v1);
1511
+ bignums = (const BIGNUM **)OPENSSL_malloc(bignums_len * (int)sizeof(BIGNUM *));
1512
+
1513
+ for (i = 0; i < bignums_len; ++i) {
1514
+ bignums[i] = GetBNPtr(rb_ary_entry(bn_v1, i));
1515
+ }
1516
+
1517
+ if (!rb_obj_is_kind_of(points_v, rb_cArray)) {
1518
+ OPENSSL_free((void *)bignums);
1519
+ rb_raise(rb_eTypeError, "Argument2 must be an array");
1520
+ }
1521
+
1522
+ rb_ary_unshift(points_v, self);
1523
+ points_len = RARRAY_LEN(points_v);
1524
+ points = (const EC_POINT **)OPENSSL_malloc(points_len * (int)sizeof(EC_POINT *));
1525
+
1526
+ for (i = 0; i < points_len; ++i) {
1527
+ Get_EC_POINT(rb_ary_entry(points_v, i), points[i]);
1528
+ }
1529
+
1530
+ if (argc >= 3) {
1531
+ bn2 = GetBNPtr(bn_v2);
1532
+ }
1533
+ if (EC_POINTs_mul(group, point2, bn2, points_len, points, bignums, ossl_bn_ctx) != 1) {
1534
+ OPENSSL_free((void *)bignums);
1535
+ OPENSSL_free((void *)points);
1536
+ ossl_raise(eEC_POINT, "Multiplication failed");
1537
+ }
1538
+ OPENSSL_free((void *)bignums);
1539
+ OPENSSL_free((void *)points);
1540
+ }
1541
+
1542
+ return r;
1543
+ }
1544
+
1463
1545
  static void no_copy(VALUE klass)
1464
1546
  {
1465
1547
  rb_undef_method(klass, "copy");
@@ -1526,7 +1608,8 @@ void Init_ossl_ec()
1526
1608
  rb_define_method(cEC, "dsa_verify_asn1", ossl_ec_key_dsa_verify_asn1, 2);
1527
1609
  /* do_sign/do_verify */
1528
1610
 
1529
- rb_define_method(cEC, "to_pem", ossl_ec_key_to_pem, 0);
1611
+ rb_define_method(cEC, "export", ossl_ec_key_export, -1);
1612
+ rb_define_alias(cEC, "to_pem", "export");
1530
1613
  rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0);
1531
1614
  rb_define_method(cEC, "to_text", ossl_ec_key_to_text, 0);
1532
1615
 
@@ -1580,6 +1663,7 @@ void Init_ossl_ec()
1580
1663
  /* all the other methods */
1581
1664
 
1582
1665
  rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, 0);
1666
+ rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1);
1583
1667
 
1584
1668
  no_copy(cEC);
1585
1669
  no_copy(cEC_GROUP);