openssl 2.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +35 -45
  3. data/History.md +426 -0
  4. data/README.md +38 -21
  5. data/ext/openssl/extconf.rb +132 -72
  6. data/ext/openssl/openssl_missing.c +0 -66
  7. data/ext/openssl/openssl_missing.h +62 -46
  8. data/ext/openssl/ossl.c +177 -252
  9. data/ext/openssl/ossl.h +39 -17
  10. data/ext/openssl/ossl_asn1.c +53 -14
  11. data/ext/openssl/ossl_bn.c +288 -146
  12. data/ext/openssl/ossl_bn.h +2 -1
  13. data/ext/openssl/ossl_cipher.c +42 -32
  14. data/ext/openssl/ossl_config.c +412 -41
  15. data/ext/openssl/ossl_config.h +4 -7
  16. data/ext/openssl/ossl_digest.c +32 -63
  17. data/ext/openssl/ossl_engine.c +19 -28
  18. data/ext/openssl/ossl_hmac.c +61 -146
  19. data/ext/openssl/ossl_kdf.c +15 -23
  20. data/ext/openssl/ossl_ns_spki.c +2 -2
  21. data/ext/openssl/ossl_ocsp.c +17 -70
  22. data/ext/openssl/ossl_ocsp.h +3 -3
  23. data/ext/openssl/ossl_pkcs12.c +23 -4
  24. data/ext/openssl/ossl_pkcs7.c +49 -81
  25. data/ext/openssl/ossl_pkcs7.h +16 -0
  26. data/ext/openssl/ossl_pkey.c +1508 -195
  27. data/ext/openssl/ossl_pkey.h +41 -78
  28. data/ext/openssl/ossl_pkey_dh.c +153 -348
  29. data/ext/openssl/ossl_pkey_dsa.c +157 -413
  30. data/ext/openssl/ossl_pkey_ec.c +257 -343
  31. data/ext/openssl/ossl_pkey_rsa.c +166 -490
  32. data/ext/openssl/ossl_provider.c +211 -0
  33. data/ext/openssl/ossl_provider.h +5 -0
  34. data/ext/openssl/ossl_rand.c +2 -40
  35. data/ext/openssl/ossl_ssl.c +666 -456
  36. data/ext/openssl/ossl_ssl_session.c +29 -30
  37. data/ext/openssl/ossl_ts.c +1539 -0
  38. data/ext/openssl/ossl_ts.h +16 -0
  39. data/ext/openssl/ossl_x509.c +86 -1
  40. data/ext/openssl/ossl_x509attr.c +1 -1
  41. data/ext/openssl/ossl_x509cert.c +170 -14
  42. data/ext/openssl/ossl_x509crl.c +14 -11
  43. data/ext/openssl/ossl_x509ext.c +29 -9
  44. data/ext/openssl/ossl_x509name.c +24 -12
  45. data/ext/openssl/ossl_x509req.c +14 -11
  46. data/ext/openssl/ossl_x509revoked.c +4 -4
  47. data/ext/openssl/ossl_x509store.c +205 -96
  48. data/lib/openssl/bn.rb +1 -1
  49. data/lib/openssl/buffering.rb +42 -20
  50. data/lib/openssl/cipher.rb +1 -1
  51. data/lib/openssl/digest.rb +10 -16
  52. data/lib/openssl/hmac.rb +78 -0
  53. data/lib/openssl/marshal.rb +30 -0
  54. data/lib/openssl/pkcs5.rb +1 -1
  55. data/lib/openssl/pkey.rb +447 -1
  56. data/lib/openssl/ssl.rb +68 -24
  57. data/lib/openssl/version.rb +5 -0
  58. data/lib/openssl/x509.rb +177 -1
  59. data/lib/openssl.rb +24 -9
  60. metadata +18 -71
  61. data/ext/openssl/deprecation.rb +0 -23
  62. data/ext/openssl/ossl_version.h +0 -15
  63. data/ext/openssl/ruby_missing.h +0 -24
  64. data/lib/openssl/config.rb +0 -474
@@ -47,12 +47,7 @@ VALUE eEC_GROUP;
47
47
  VALUE cEC_POINT;
48
48
  VALUE eEC_POINT;
49
49
 
50
- static ID s_GFp;
51
- static ID s_GFp_simple;
52
- static ID s_GFp_mont;
53
- static ID s_GFp_nist;
54
- static ID s_GF2m;
55
- static ID s_GF2m_simple;
50
+ static ID s_GFp, s_GF2m;
56
51
 
57
52
  static ID ID_uncompressed;
58
53
  static ID ID_compressed;
@@ -63,47 +58,6 @@ static ID id_i_group;
63
58
  static VALUE ec_group_new(const EC_GROUP *group);
64
59
  static VALUE ec_point_new(const EC_POINT *point, const EC_GROUP *group);
65
60
 
66
- static VALUE ec_instance(VALUE klass, EC_KEY *ec)
67
- {
68
- EVP_PKEY *pkey;
69
- VALUE obj;
70
-
71
- if (!ec) {
72
- return Qfalse;
73
- }
74
- obj = NewPKey(klass);
75
- if (!(pkey = EVP_PKEY_new())) {
76
- return Qfalse;
77
- }
78
- if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
79
- EVP_PKEY_free(pkey);
80
- return Qfalse;
81
- }
82
- SetPKey(obj, pkey);
83
-
84
- return obj;
85
- }
86
-
87
- VALUE ossl_ec_new(EVP_PKEY *pkey)
88
- {
89
- VALUE obj;
90
-
91
- if (!pkey) {
92
- obj = ec_instance(cEC, EC_KEY_new());
93
- } else {
94
- obj = NewPKey(cEC);
95
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) {
96
- ossl_raise(rb_eTypeError, "Not a EC key!");
97
- }
98
- SetPKey(obj, pkey);
99
- }
100
- if (obj == Qfalse) {
101
- ossl_raise(eECError, NULL);
102
- }
103
-
104
- return obj;
105
- }
106
-
107
61
  /*
108
62
  * Creates a new EC_KEY on the EC group obj. arg can be an EC::Group or a String
109
63
  * representing an OID.
@@ -150,16 +104,20 @@ ec_key_new_from_group(VALUE arg)
150
104
  static VALUE
151
105
  ossl_ec_key_s_generate(VALUE klass, VALUE arg)
152
106
  {
107
+ EVP_PKEY *pkey;
153
108
  EC_KEY *ec;
154
109
  VALUE obj;
155
110
 
156
- ec = ec_key_new_from_group(arg);
111
+ obj = rb_obj_alloc(klass);
157
112
 
158
- obj = ec_instance(klass, ec);
159
- if (obj == Qfalse) {
160
- EC_KEY_free(ec);
161
- ossl_raise(eECError, NULL);
113
+ ec = ec_key_new_from_group(arg);
114
+ pkey = EVP_PKEY_new();
115
+ if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) {
116
+ EVP_PKEY_free(pkey);
117
+ EC_KEY_free(ec);
118
+ ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
162
119
  }
120
+ RTYPEDDATA_DATA(obj) = pkey;
163
121
 
164
122
  if (!EC_KEY_generate_key(ec))
165
123
  ossl_raise(eECError, "EC_KEY_generate_key");
@@ -182,81 +140,82 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
182
140
  {
183
141
  EVP_PKEY *pkey;
184
142
  EC_KEY *ec;
143
+ BIO *in;
185
144
  VALUE arg, pass;
145
+ int type;
186
146
 
187
- GetPKey(self, pkey);
188
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
189
- ossl_raise(eECError, "EC_KEY already initialized");
147
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
148
+ if (pkey)
149
+ rb_raise(rb_eTypeError, "pkey already initialized");
190
150
 
191
151
  rb_scan_args(argc, argv, "02", &arg, &pass);
192
-
193
152
  if (NIL_P(arg)) {
194
153
  if (!(ec = EC_KEY_new()))
195
- ossl_raise(eECError, NULL);
196
- } else if (rb_obj_is_kind_of(arg, cEC)) {
197
- EC_KEY *other_ec = NULL;
198
-
199
- GetEC(arg, other_ec);
200
- if (!(ec = EC_KEY_dup(other_ec)))
201
- ossl_raise(eECError, NULL);
202
- } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
203
- ec = ec_key_new_from_group(arg);
204
- } else {
205
- BIO *in;
206
-
207
- pass = ossl_pem_passwd_value(pass);
208
- in = ossl_obj2bio(&arg);
154
+ ossl_raise(eECError, "EC_KEY_new");
155
+ goto legacy;
156
+ }
157
+ else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
158
+ ec = ec_key_new_from_group(arg);
159
+ goto legacy;
160
+ }
209
161
 
210
- ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass);
211
- if (!ec) {
212
- OSSL_BIO_reset(in);
213
- ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, (void *)pass);
214
- }
215
- if (!ec) {
216
- OSSL_BIO_reset(in);
217
- ec = d2i_ECPrivateKey_bio(in, NULL);
218
- }
219
- if (!ec) {
220
- OSSL_BIO_reset(in);
221
- ec = d2i_EC_PUBKEY_bio(in, NULL);
222
- }
223
- BIO_free(in);
162
+ pass = ossl_pem_passwd_value(pass);
163
+ arg = ossl_to_der_if_possible(arg);
164
+ in = ossl_obj2bio(&arg);
224
165
 
225
- if (!ec) {
226
- ossl_clear_error();
227
- ec = ec_key_new_from_group(arg);
228
- }
166
+ pkey = ossl_pkey_read_generic(in, pass);
167
+ BIO_free(in);
168
+ if (!pkey) {
169
+ ossl_clear_error();
170
+ ec = ec_key_new_from_group(arg);
171
+ goto legacy;
229
172
  }
230
173
 
231
- if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
232
- EC_KEY_free(ec);
233
- ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
174
+ type = EVP_PKEY_base_id(pkey);
175
+ if (type != EVP_PKEY_EC) {
176
+ EVP_PKEY_free(pkey);
177
+ rb_raise(eDSAError, "incorrect pkey type: %s", OBJ_nid2sn(type));
234
178
  }
179
+ RTYPEDDATA_DATA(self) = pkey;
180
+ return self;
235
181
 
182
+ legacy:
183
+ pkey = EVP_PKEY_new();
184
+ if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec) != 1) {
185
+ EVP_PKEY_free(pkey);
186
+ EC_KEY_free(ec);
187
+ ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
188
+ }
189
+ RTYPEDDATA_DATA(self) = pkey;
236
190
  return self;
237
191
  }
238
192
 
193
+ #ifndef HAVE_EVP_PKEY_DUP
239
194
  static VALUE
240
195
  ossl_ec_key_initialize_copy(VALUE self, VALUE other)
241
196
  {
242
197
  EVP_PKEY *pkey;
243
198
  EC_KEY *ec, *ec_new;
244
199
 
245
- GetPKey(self, pkey);
246
- if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
247
- ossl_raise(eECError, "EC already initialized");
200
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
201
+ if (pkey)
202
+ rb_raise(rb_eTypeError, "pkey already initialized");
248
203
  GetEC(other, ec);
249
204
 
250
205
  ec_new = EC_KEY_dup(ec);
251
206
  if (!ec_new)
252
207
  ossl_raise(eECError, "EC_KEY_dup");
253
- if (!EVP_PKEY_assign_EC_KEY(pkey, ec_new)) {
254
- EC_KEY_free(ec_new);
255
- ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
208
+
209
+ pkey = EVP_PKEY_new();
210
+ if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, ec_new) != 1) {
211
+ EC_KEY_free(ec_new);
212
+ ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
256
213
  }
214
+ RTYPEDDATA_DATA(self) = pkey;
257
215
 
258
216
  return self;
259
217
  }
218
+ #endif
260
219
 
261
220
  /*
262
221
  * call-seq:
@@ -268,7 +227,7 @@ ossl_ec_key_initialize_copy(VALUE self, VALUE other)
268
227
  static VALUE
269
228
  ossl_ec_key_get_group(VALUE self)
270
229
  {
271
- EC_KEY *ec;
230
+ OSSL_3_const EC_KEY *ec;
272
231
  const EC_GROUP *group;
273
232
 
274
233
  GetEC(self, ec);
@@ -289,6 +248,9 @@ ossl_ec_key_get_group(VALUE self)
289
248
  static VALUE
290
249
  ossl_ec_key_set_group(VALUE self, VALUE group_v)
291
250
  {
251
+ #if OSSL_OPENSSL_PREREQ(3, 0, 0)
252
+ rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
253
+ #else
292
254
  EC_KEY *ec;
293
255
  EC_GROUP *group;
294
256
 
@@ -299,6 +261,7 @@ ossl_ec_key_set_group(VALUE self, VALUE group_v)
299
261
  ossl_raise(eECError, "EC_KEY_set_group");
300
262
 
301
263
  return group_v;
264
+ #endif
302
265
  }
303
266
 
304
267
  /*
@@ -309,7 +272,7 @@ ossl_ec_key_set_group(VALUE self, VALUE group_v)
309
272
  */
310
273
  static VALUE ossl_ec_key_get_private_key(VALUE self)
311
274
  {
312
- EC_KEY *ec;
275
+ OSSL_3_const EC_KEY *ec;
313
276
  const BIGNUM *bn;
314
277
 
315
278
  GetEC(self, ec);
@@ -327,6 +290,9 @@ static VALUE ossl_ec_key_get_private_key(VALUE self)
327
290
  */
328
291
  static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
329
292
  {
293
+ #if OSSL_OPENSSL_PREREQ(3, 0, 0)
294
+ rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
295
+ #else
330
296
  EC_KEY *ec;
331
297
  BIGNUM *bn = NULL;
332
298
 
@@ -340,11 +306,13 @@ static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
340
306
  case 0:
341
307
  if (bn == NULL)
342
308
  break;
309
+ /* fallthrough */
343
310
  default:
344
311
  ossl_raise(eECError, "EC_KEY_set_private_key");
345
312
  }
346
313
 
347
314
  return private_key;
315
+ #endif
348
316
  }
349
317
 
350
318
  /*
@@ -355,7 +323,7 @@ static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
355
323
  */
356
324
  static VALUE ossl_ec_key_get_public_key(VALUE self)
357
325
  {
358
- EC_KEY *ec;
326
+ OSSL_3_const EC_KEY *ec;
359
327
  const EC_POINT *point;
360
328
 
361
329
  GetEC(self, ec);
@@ -373,6 +341,9 @@ static VALUE ossl_ec_key_get_public_key(VALUE self)
373
341
  */
374
342
  static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
375
343
  {
344
+ #if OSSL_OPENSSL_PREREQ(3, 0, 0)
345
+ rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
346
+ #else
376
347
  EC_KEY *ec;
377
348
  EC_POINT *point = NULL;
378
349
 
@@ -386,11 +357,13 @@ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
386
357
  case 0:
387
358
  if (point == NULL)
388
359
  break;
360
+ /* fallthrough */
389
361
  default:
390
362
  ossl_raise(eECError, "EC_KEY_set_public_key");
391
363
  }
392
364
 
393
365
  return public_key;
366
+ #endif
394
367
  }
395
368
 
396
369
  /*
@@ -402,7 +375,7 @@ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
402
375
  */
403
376
  static VALUE ossl_ec_key_is_public(VALUE self)
404
377
  {
405
- EC_KEY *ec;
378
+ OSSL_3_const EC_KEY *ec;
406
379
 
407
380
  GetEC(self, ec);
408
381
 
@@ -418,126 +391,112 @@ static VALUE ossl_ec_key_is_public(VALUE self)
418
391
  */
419
392
  static VALUE ossl_ec_key_is_private(VALUE self)
420
393
  {
421
- EC_KEY *ec;
394
+ OSSL_3_const EC_KEY *ec;
422
395
 
423
396
  GetEC(self, ec);
424
397
 
425
398
  return EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse;
426
399
  }
427
400
 
428
- static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int format)
401
+ /*
402
+ * call-seq:
403
+ * key.export([cipher, password]) => String
404
+ * key.to_pem([cipher, password]) => String
405
+ *
406
+ * Serializes a private or public key to a PEM-encoding.
407
+ *
408
+ * [When the key contains public components only]
409
+ *
410
+ * Serializes it into an X.509 SubjectPublicKeyInfo.
411
+ * The parameters _cipher_ and _password_ are ignored.
412
+ *
413
+ * A PEM-encoded key will look like:
414
+ *
415
+ * -----BEGIN PUBLIC KEY-----
416
+ * [...]
417
+ * -----END PUBLIC KEY-----
418
+ *
419
+ * Consider using #public_to_pem instead. This serializes the key into an
420
+ * X.509 SubjectPublicKeyInfo regardless of whether it is a public key
421
+ * or a private key.
422
+ *
423
+ * [When the key contains private components, and no parameters are given]
424
+ *
425
+ * Serializes it into a SEC 1/RFC 5915 ECPrivateKey.
426
+ *
427
+ * A PEM-encoded key will look like:
428
+ *
429
+ * -----BEGIN EC PRIVATE KEY-----
430
+ * [...]
431
+ * -----END EC PRIVATE KEY-----
432
+ *
433
+ * [When the key contains private components, and _cipher_ and _password_ are given]
434
+ *
435
+ * Serializes it into a SEC 1/RFC 5915 ECPrivateKey
436
+ * and encrypts it in OpenSSL's traditional PEM encryption format.
437
+ * _cipher_ must be a cipher name understood by OpenSSL::Cipher.new or an
438
+ * instance of OpenSSL::Cipher.
439
+ *
440
+ * An encrypted PEM-encoded key will look like:
441
+ *
442
+ * -----BEGIN EC PRIVATE KEY-----
443
+ * Proc-Type: 4,ENCRYPTED
444
+ * DEK-Info: AES-128-CBC,733F5302505B34701FC41F5C0746E4C0
445
+ *
446
+ * [...]
447
+ * -----END EC PRIVATE KEY-----
448
+ *
449
+ * Note that this format uses MD5 to derive the encryption key, and hence
450
+ * will not be available on FIPS-compliant systems.
451
+ *
452
+ * <b>This method is kept for compatibility.</b>
453
+ * This should only be used when the SEC 1/RFC 5915 ECPrivateKey format is
454
+ * required.
455
+ *
456
+ * Consider using #public_to_pem (X.509 SubjectPublicKeyInfo) or #private_to_pem
457
+ * (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) instead.
458
+ */
459
+ static VALUE
460
+ ossl_ec_key_export(int argc, VALUE *argv, VALUE self)
429
461
  {
430
- EC_KEY *ec;
431
- BIO *out;
432
- int i = -1;
433
- int private = 0;
434
- VALUE str;
435
- const EVP_CIPHER *cipher = NULL;
462
+ OSSL_3_const EC_KEY *ec;
436
463
 
437
464
  GetEC(self, ec);
438
-
439
465
  if (EC_KEY_get0_public_key(ec) == NULL)
440
466
  ossl_raise(eECError, "can't export - no public key set");
441
-
442
- if (EC_KEY_check_key(ec) != 1)
443
- ossl_raise(eECError, "can't export - EC_KEY_check_key failed");
444
-
445
467
  if (EC_KEY_get0_private_key(ec))
446
- private = 1;
447
-
448
- if (!NIL_P(ciph)) {
449
- cipher = ossl_evp_get_cipherbyname(ciph);
450
- pass = ossl_pem_passwd_value(pass);
451
- }
452
-
453
- if (!(out = BIO_new(BIO_s_mem())))
454
- ossl_raise(eECError, "BIO_new(BIO_s_mem())");
455
-
456
- switch(format) {
457
- case EXPORT_PEM:
458
- if (private) {
459
- i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, ossl_pem_passwd_cb, (void *)pass);
460
- } else {
461
- i = PEM_write_bio_EC_PUBKEY(out, ec);
462
- }
463
-
464
- break;
465
- case EXPORT_DER:
466
- if (private) {
467
- i = i2d_ECPrivateKey_bio(out, ec);
468
- } else {
469
- i = i2d_EC_PUBKEY_bio(out, ec);
470
- }
471
-
472
- break;
473
- default:
474
- BIO_free(out);
475
- ossl_raise(rb_eRuntimeError, "unknown format (internal error)");
476
- }
477
-
478
- if (i != 1) {
479
- BIO_free(out);
480
- ossl_raise(eECError, "outlen=%d", i);
481
- }
482
-
483
- str = ossl_membio2str(out);
484
-
485
- return str;
486
- }
487
-
488
- /*
489
- * call-seq:
490
- * key.export([cipher, pass_phrase]) => String
491
- * key.to_pem([cipher, pass_phrase]) => String
492
- *
493
- * Outputs the EC key in PEM encoding. If _cipher_ and _pass_phrase_ are given
494
- * they will be used to encrypt the key. _cipher_ must be an OpenSSL::Cipher
495
- * instance. Note that encryption will only be effective for a private key,
496
- * public keys will always be encoded in plain text.
497
- */
498
- static VALUE ossl_ec_key_export(int argc, VALUE *argv, VALUE self)
499
- {
500
- VALUE cipher, passwd;
501
- rb_scan_args(argc, argv, "02", &cipher, &passwd);
502
- return ossl_ec_key_to_string(self, cipher, passwd, EXPORT_PEM);
468
+ return ossl_pkey_export_traditional(argc, argv, self, 0);
469
+ else
470
+ return ossl_pkey_export_spki(self, 0);
503
471
  }
504
472
 
505
473
  /*
506
474
  * call-seq:
507
475
  * key.to_der => String
508
476
  *
509
- * See the OpenSSL documentation for i2d_ECPrivateKey_bio()
510
- */
511
- static VALUE ossl_ec_key_to_der(VALUE self)
512
- {
513
- return ossl_ec_key_to_string(self, Qnil, Qnil, EXPORT_DER);
514
- }
515
-
516
- /*
517
- * call-seq:
518
- * key.to_text => String
477
+ * Serializes a private or public key to a DER-encoding.
478
+ *
479
+ * See #to_pem for details.
519
480
  *
520
- * See the OpenSSL documentation for EC_KEY_print()
481
+ * <b>This method is kept for compatibility.</b>
482
+ * This should only be used when the SEC 1/RFC 5915 ECPrivateKey format is
483
+ * required.
484
+ *
485
+ * Consider using #public_to_der or #private_to_der instead.
521
486
  */
522
- static VALUE ossl_ec_key_to_text(VALUE self)
487
+ static VALUE
488
+ ossl_ec_key_to_der(VALUE self)
523
489
  {
524
- EC_KEY *ec;
525
- BIO *out;
526
- VALUE str;
490
+ OSSL_3_const EC_KEY *ec;
527
491
 
528
492
  GetEC(self, ec);
529
- if (!(out = BIO_new(BIO_s_mem()))) {
530
- ossl_raise(eECError, "BIO_new(BIO_s_mem())");
531
- }
532
- if (!EC_KEY_print(out, ec, 0)) {
533
- BIO_free(out);
534
- ossl_raise(eECError, "EC_KEY_print");
535
- }
536
- str = ossl_membio2str(out);
537
-
538
- return str;
493
+ if (EC_KEY_get0_public_key(ec) == NULL)
494
+ ossl_raise(eECError, "can't export - no public key set");
495
+ if (EC_KEY_get0_private_key(ec))
496
+ return ossl_pkey_export_traditional(0, NULL, self, 1);
497
+ else
498
+ return ossl_pkey_export_spki(self, 1);
539
499
  }
540
-
541
500
  /*
542
501
  * call-seq:
543
502
  * key.generate_key! => self
@@ -554,6 +513,9 @@ static VALUE ossl_ec_key_to_text(VALUE self)
554
513
  */
555
514
  static VALUE ossl_ec_key_generate_key(VALUE self)
556
515
  {
516
+ #if OSSL_OPENSSL_PREREQ(3, 0, 0)
517
+ rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
518
+ #else
557
519
  EC_KEY *ec;
558
520
 
559
521
  GetEC(self, ec);
@@ -561,107 +523,53 @@ static VALUE ossl_ec_key_generate_key(VALUE self)
561
523
  ossl_raise(eECError, "EC_KEY_generate_key");
562
524
 
563
525
  return self;
526
+ #endif
564
527
  }
565
528
 
566
529
  /*
567
- * call-seq:
568
- * key.check_key => true
530
+ * call-seq:
531
+ * key.check_key => true
569
532
  *
570
- * Raises an exception if the key is invalid.
533
+ * Raises an exception if the key is invalid.
571
534
  *
572
- * See the OpenSSL documentation for EC_KEY_check_key()
535
+ * See also the man page EVP_PKEY_public_check(3).
573
536
  */
574
537
  static VALUE ossl_ec_key_check_key(VALUE self)
575
538
  {
576
- EC_KEY *ec;
577
-
578
- GetEC(self, ec);
579
- if (EC_KEY_check_key(ec) != 1)
580
- ossl_raise(eECError, "EC_KEY_check_key");
581
-
582
- return Qtrue;
583
- }
584
-
585
- /*
586
- * call-seq:
587
- * key.dh_compute_key(pubkey) => String
588
- *
589
- * See the OpenSSL documentation for ECDH_compute_key()
590
- */
591
- static VALUE ossl_ec_key_dh_compute_key(VALUE self, VALUE pubkey)
592
- {
593
- EC_KEY *ec;
594
- EC_POINT *point;
595
- int buf_len;
596
- VALUE str;
597
-
598
- GetEC(self, ec);
599
- GetECPoint(pubkey, point);
600
-
601
- /* BUG: need a way to figure out the maximum string size */
602
- buf_len = 1024;
603
- str = rb_str_new(0, buf_len);
604
- /* BUG: take KDF as a block */
605
- buf_len = ECDH_compute_key(RSTRING_PTR(str), buf_len, point, ec, NULL);
606
- if (buf_len < 0)
607
- ossl_raise(eECError, "ECDH_compute_key");
608
-
609
- rb_str_resize(str, buf_len);
610
-
611
- return str;
612
- }
613
-
614
- /* sign_setup */
615
-
616
- /*
617
- * call-seq:
618
- * key.dsa_sign_asn1(data) => String
619
- *
620
- * See the OpenSSL documentation for ECDSA_sign()
621
- */
622
- static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data)
623
- {
624
- EC_KEY *ec;
625
- unsigned int buf_len;
626
- VALUE str;
539
+ #ifdef HAVE_EVP_PKEY_CHECK
540
+ EVP_PKEY *pkey;
541
+ EVP_PKEY_CTX *pctx;
542
+ const EC_KEY *ec;
627
543
 
544
+ GetPKey(self, pkey);
628
545
  GetEC(self, ec);
629
- StringValue(data);
630
-
631
- if (EC_KEY_get0_private_key(ec) == NULL)
632
- ossl_raise(eECError, "Private EC key needed!");
633
-
634
- str = rb_str_new(0, ECDSA_size(ec));
635
- if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1)
636
- ossl_raise(eECError, "ECDSA_sign");
637
- rb_str_set_len(str, buf_len);
638
-
639
- return str;
640
- }
546
+ pctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
547
+ if (!pctx)
548
+ ossl_raise(eECError, "EVP_PKEY_CTX_new");
549
+
550
+ if (EC_KEY_get0_private_key(ec) != NULL) {
551
+ if (EVP_PKEY_check(pctx) != 1) {
552
+ EVP_PKEY_CTX_free(pctx);
553
+ ossl_raise(eECError, "EVP_PKEY_check");
554
+ }
555
+ }
556
+ else {
557
+ if (EVP_PKEY_public_check(pctx) != 1) {
558
+ EVP_PKEY_CTX_free(pctx);
559
+ ossl_raise(eECError, "EVP_PKEY_public_check");
560
+ }
561
+ }
641
562
 
642
- /*
643
- * call-seq:
644
- * key.dsa_verify_asn1(data, sig) => true or false
645
- *
646
- * See the OpenSSL documentation for ECDSA_verify()
647
- */
648
- static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
649
- {
563
+ EVP_PKEY_CTX_free(pctx);
564
+ #else
650
565
  EC_KEY *ec;
651
566
 
652
567
  GetEC(self, ec);
653
- StringValue(data);
654
- StringValue(sig);
655
-
656
- switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(sig), (int)RSTRING_LEN(sig), ec)) {
657
- case 1: return Qtrue;
658
- case 0: return Qfalse;
659
- default: break;
660
- }
661
-
662
- ossl_raise(eECError, "ECDSA_verify");
568
+ if (EC_KEY_check_key(ec) != 1)
569
+ ossl_raise(eECError, "EC_KEY_check_key");
570
+ #endif
663
571
 
664
- UNREACHABLE;
572
+ return Qtrue;
665
573
  }
666
574
 
667
575
  /*
@@ -670,7 +578,7 @@ static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
670
578
  static void
671
579
  ossl_ec_group_free(void *ptr)
672
580
  {
673
- EC_GROUP_clear_free(ptr);
581
+ EC_GROUP_free(ptr);
674
582
  }
675
583
 
676
584
  static const rb_data_type_t ossl_ec_group_type = {
@@ -678,7 +586,7 @@ static const rb_data_type_t ossl_ec_group_type = {
678
586
  {
679
587
  0, ossl_ec_group_free,
680
588
  },
681
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
589
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
682
590
  };
683
591
 
684
592
  static VALUE
@@ -706,20 +614,11 @@ ec_group_new(const EC_GROUP *group)
706
614
  * call-seq:
707
615
  * OpenSSL::PKey::EC::Group.new(ec_group)
708
616
  * OpenSSL::PKey::EC::Group.new(pem_or_der_encoded)
709
- * OpenSSL::PKey::EC::Group.new(ec_method)
710
617
  * OpenSSL::PKey::EC::Group.new(:GFp, bignum_p, bignum_a, bignum_b)
711
618
  * OpenSSL::PKey::EC::Group.new(:GF2m, bignum_p, bignum_a, bignum_b)
712
619
  *
713
620
  * Creates a new EC::Group object.
714
621
  *
715
- * _ec_method_ is a symbol that represents an EC_METHOD. Currently the following
716
- * are supported:
717
- *
718
- * * :GFp_simple
719
- * * :GFp_mont
720
- * * :GFp_nist
721
- * * :GF2m_simple
722
- *
723
622
  * If the first argument is :GFp or :GF2m, creates a new curve with given
724
623
  * parameters.
725
624
  */
@@ -734,29 +633,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
734
633
 
735
634
  switch (rb_scan_args(argc, argv, "13", &arg1, &arg2, &arg3, &arg4)) {
736
635
  case 1:
737
- if (SYMBOL_P(arg1)) {
738
- const EC_METHOD *method = NULL;
739
- ID id = SYM2ID(arg1);
740
-
741
- if (id == s_GFp_simple) {
742
- method = EC_GFp_simple_method();
743
- } else if (id == s_GFp_mont) {
744
- method = EC_GFp_mont_method();
745
- } else if (id == s_GFp_nist) {
746
- method = EC_GFp_nist_method();
747
- #if !defined(OPENSSL_NO_EC2M)
748
- } else if (id == s_GF2m_simple) {
749
- method = EC_GF2m_simple_method();
750
- #endif
751
- }
752
-
753
- if (method) {
754
- if ((group = EC_GROUP_new(method)) == NULL)
755
- ossl_raise(eEC_GROUP, "EC_GROUP_new");
756
- } else {
757
- ossl_raise(rb_eArgError, "unknown symbol, must be :GFp_simple, :GFp_mont, :GFp_nist or :GF2m_simple");
758
- }
759
- } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
636
+ if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
760
637
  const EC_GROUP *arg1_group;
761
638
 
762
639
  GetECGroup(arg1, arg1_group);
@@ -820,8 +697,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
820
697
  ossl_raise(rb_eArgError, "wrong number of arguments");
821
698
  }
822
699
 
823
- if (group == NULL)
824
- ossl_raise(eEC_GROUP, "");
700
+ ASSUME(group);
825
701
  RTYPEDDATA_DATA(self) = group;
826
702
 
827
703
  return self;
@@ -860,10 +736,11 @@ static VALUE ossl_ec_group_eql(VALUE a, VALUE b)
860
736
  GetECGroup(a, group1);
861
737
  GetECGroup(b, group2);
862
738
 
863
- if (EC_GROUP_cmp(group1, group2, ossl_bn_ctx) == 1)
864
- return Qfalse;
865
-
866
- return Qtrue;
739
+ switch (EC_GROUP_cmp(group1, group2, ossl_bn_ctx)) {
740
+ case 0: return Qtrue;
741
+ case 1: return Qfalse;
742
+ default: ossl_raise(eEC_GROUP, "EC_GROUP_cmp");
743
+ }
867
744
  }
868
745
 
869
746
  /*
@@ -1294,7 +1171,7 @@ static const rb_data_type_t ossl_ec_point_type = {
1294
1171
  {
1295
1172
  0, ossl_ec_point_free,
1296
1173
  },
1297
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
1174
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1298
1175
  };
1299
1176
 
1300
1177
  static VALUE
@@ -1424,10 +1301,13 @@ static VALUE ossl_ec_point_eql(VALUE a, VALUE b)
1424
1301
  GetECPoint(b, point2);
1425
1302
  GetECGroup(group_v1, group);
1426
1303
 
1427
- if (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx) == 1)
1428
- return Qfalse;
1304
+ switch (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx)) {
1305
+ case 0: return Qtrue;
1306
+ case 1: return Qfalse;
1307
+ default: ossl_raise(eEC_POINT, "EC_POINT_cmp");
1308
+ }
1429
1309
 
1430
- return Qtrue;
1310
+ UNREACHABLE;
1431
1311
  }
1432
1312
 
1433
1313
  /*
@@ -1445,7 +1325,7 @@ static VALUE ossl_ec_point_is_at_infinity(VALUE self)
1445
1325
  switch (EC_POINT_is_at_infinity(group, point)) {
1446
1326
  case 1: return Qtrue;
1447
1327
  case 0: return Qfalse;
1448
- default: ossl_raise(cEC_POINT, "EC_POINT_is_at_infinity");
1328
+ default: ossl_raise(eEC_POINT, "EC_POINT_is_at_infinity");
1449
1329
  }
1450
1330
 
1451
1331
  UNREACHABLE;
@@ -1466,7 +1346,7 @@ static VALUE ossl_ec_point_is_on_curve(VALUE self)
1466
1346
  switch (EC_POINT_is_on_curve(group, point, ossl_bn_ctx)) {
1467
1347
  case 1: return Qtrue;
1468
1348
  case 0: return Qfalse;
1469
- default: ossl_raise(cEC_POINT, "EC_POINT_is_on_curve");
1349
+ default: ossl_raise(eEC_POINT, "EC_POINT_is_on_curve");
1470
1350
  }
1471
1351
 
1472
1352
  UNREACHABLE;
@@ -1475,6 +1355,8 @@ static VALUE ossl_ec_point_is_on_curve(VALUE self)
1475
1355
  /*
1476
1356
  * call-seq:
1477
1357
  * point.make_affine! => self
1358
+ *
1359
+ * This method is deprecated and should not be used. This is a no-op.
1478
1360
  */
1479
1361
  static VALUE ossl_ec_point_make_affine(VALUE self)
1480
1362
  {
@@ -1484,8 +1366,11 @@ static VALUE ossl_ec_point_make_affine(VALUE self)
1484
1366
  GetECPoint(self, point);
1485
1367
  GetECPointGroup(self, group);
1486
1368
 
1369
+ rb_warn("OpenSSL::PKey::EC::Point#make_affine! is deprecated");
1370
+ #if !OSSL_OPENSSL_PREREQ(3, 0, 0)
1487
1371
  if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1)
1488
- ossl_raise(cEC_POINT, "EC_POINT_make_affine");
1372
+ ossl_raise(eEC_POINT, "EC_POINT_make_affine");
1373
+ #endif
1489
1374
 
1490
1375
  return self;
1491
1376
  }
@@ -1503,7 +1388,7 @@ static VALUE ossl_ec_point_invert(VALUE self)
1503
1388
  GetECPointGroup(self, group);
1504
1389
 
1505
1390
  if (EC_POINT_invert(group, point, ossl_bn_ctx) != 1)
1506
- ossl_raise(cEC_POINT, "EC_POINT_invert");
1391
+ ossl_raise(eEC_POINT, "EC_POINT_invert");
1507
1392
 
1508
1393
  return self;
1509
1394
  }
@@ -1521,7 +1406,7 @@ static VALUE ossl_ec_point_set_to_infinity(VALUE self)
1521
1406
  GetECPointGroup(self, group);
1522
1407
 
1523
1408
  if (EC_POINT_set_to_infinity(group, point) != 1)
1524
- ossl_raise(cEC_POINT, "EC_POINT_set_to_infinity");
1409
+ ossl_raise(eEC_POINT, "EC_POINT_set_to_infinity");
1525
1410
 
1526
1411
  return self;
1527
1412
  }
@@ -1562,6 +1447,34 @@ ossl_ec_point_to_octet_string(VALUE self, VALUE conversion_form)
1562
1447
  return str;
1563
1448
  }
1564
1449
 
1450
+ /*
1451
+ * call-seq:
1452
+ * point.add(point) => point
1453
+ *
1454
+ * Performs elliptic curve point addition.
1455
+ */
1456
+ static VALUE ossl_ec_point_add(VALUE self, VALUE other)
1457
+ {
1458
+ EC_POINT *point_self, *point_other, *point_result;
1459
+ const EC_GROUP *group;
1460
+ VALUE group_v = rb_attr_get(self, id_i_group);
1461
+ VALUE result;
1462
+
1463
+ GetECPoint(self, point_self);
1464
+ GetECPoint(other, point_other);
1465
+ GetECGroup(group_v, group);
1466
+
1467
+ result = rb_obj_alloc(cEC_POINT);
1468
+ ossl_ec_point_initialize(1, &group_v, result);
1469
+ GetECPoint(result, point_result);
1470
+
1471
+ if (EC_POINT_add(group, point_result, point_self, point_other, ossl_bn_ctx) != 1) {
1472
+ ossl_raise(eEC_POINT, "EC_POINT_add");
1473
+ }
1474
+
1475
+ return result;
1476
+ }
1477
+
1565
1478
  /*
1566
1479
  * call-seq:
1567
1480
  * point.mul(bn1 [, bn2]) => point
@@ -1603,6 +1516,10 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
1603
1516
  if (EC_POINT_mul(group, point_result, bn_g, point_self, bn, ossl_bn_ctx) != 1)
1604
1517
  ossl_raise(eEC_POINT, NULL);
1605
1518
  } else {
1519
+ #if (defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3) || defined(LIBRESSL_VERSION_NUMBER)
1520
+ rb_raise(rb_eNotImpError, "calling #mul with arrays is not" \
1521
+ "supported by this OpenSSL version");
1522
+ #else
1606
1523
  /*
1607
1524
  * bignums | arg1[0] | arg1[1] | arg1[2] | ...
1608
1525
  * points | self | arg2[0] | arg2[1] | ...
@@ -1617,6 +1534,9 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
1617
1534
  if (RARRAY_LEN(arg1) != RARRAY_LEN(arg2) + 1) /* arg2 must be 1 larger */
1618
1535
  ossl_raise(rb_eArgError, "bns must be 1 longer than points; see the documentation");
1619
1536
 
1537
+ rb_warning("OpenSSL::PKey::EC::Point#mul(ary, ary) is deprecated; " \
1538
+ "use #mul(bn) form instead");
1539
+
1620
1540
  num = RARRAY_LEN(arg1);
1621
1541
  bns_tmp = rb_ary_tmp_new(num);
1622
1542
  bignums = ALLOCV_N(const BIGNUM *, tmp_b, num);
@@ -1642,6 +1562,7 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
1642
1562
 
1643
1563
  ALLOCV_END(tmp_b);
1644
1564
  ALLOCV_END(tmp_p);
1565
+ #endif
1645
1566
  }
1646
1567
 
1647
1568
  return result;
@@ -1649,6 +1570,7 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
1649
1570
 
1650
1571
  void Init_ossl_ec(void)
1651
1572
  {
1573
+ #undef rb_intern
1652
1574
  #if 0
1653
1575
  mPKey = rb_define_module_under(mOSSL, "PKey");
1654
1576
  cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
@@ -1681,10 +1603,6 @@ void Init_ossl_ec(void)
1681
1603
 
1682
1604
  s_GFp = rb_intern("GFp");
1683
1605
  s_GF2m = rb_intern("GF2m");
1684
- s_GFp_simple = rb_intern("GFp_simple");
1685
- s_GFp_mont = rb_intern("GFp_mont");
1686
- s_GFp_nist = rb_intern("GFp_nist");
1687
- s_GF2m_simple = rb_intern("GF2m_simple");
1688
1606
 
1689
1607
  ID_uncompressed = rb_intern("uncompressed");
1690
1608
  ID_compressed = rb_intern("compressed");
@@ -1699,8 +1617,9 @@ void Init_ossl_ec(void)
1699
1617
 
1700
1618
  rb_define_singleton_method(cEC, "generate", ossl_ec_key_s_generate, 1);
1701
1619
  rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1);
1620
+ #ifndef HAVE_EVP_PKEY_DUP
1702
1621
  rb_define_method(cEC, "initialize_copy", ossl_ec_key_initialize_copy, 1);
1703
- /* copy/dup/cmp */
1622
+ #endif
1704
1623
 
1705
1624
  rb_define_method(cEC, "group", ossl_ec_key_get_group, 0);
1706
1625
  rb_define_method(cEC, "group=", ossl_ec_key_set_group, 1);
@@ -1723,15 +1642,9 @@ void Init_ossl_ec(void)
1723
1642
  rb_define_alias(cEC, "generate_key", "generate_key!");
1724
1643
  rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0);
1725
1644
 
1726
- rb_define_method(cEC, "dh_compute_key", ossl_ec_key_dh_compute_key, 1);
1727
- rb_define_method(cEC, "dsa_sign_asn1", ossl_ec_key_dsa_sign_asn1, 1);
1728
- rb_define_method(cEC, "dsa_verify_asn1", ossl_ec_key_dsa_verify_asn1, 2);
1729
- /* do_sign/do_verify */
1730
-
1731
1645
  rb_define_method(cEC, "export", ossl_ec_key_export, -1);
1732
1646
  rb_define_alias(cEC, "to_pem", "export");
1733
1647
  rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0);
1734
- rb_define_method(cEC, "to_text", ossl_ec_key_to_text, 0);
1735
1648
 
1736
1649
 
1737
1650
  rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc);
@@ -1785,6 +1698,7 @@ void Init_ossl_ec(void)
1785
1698
  /* all the other methods */
1786
1699
 
1787
1700
  rb_define_method(cEC_POINT, "to_octet_string", ossl_ec_point_to_octet_string, 1);
1701
+ rb_define_method(cEC_POINT, "add", ossl_ec_point_add, 1);
1788
1702
  rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1);
1789
1703
 
1790
1704
  id_i_group = rb_intern("@group");