openssl 2.2.1 → 3.2.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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +33 -45
  3. data/History.md +248 -1
  4. data/README.md +36 -19
  5. data/ext/openssl/extconf.rb +101 -68
  6. data/ext/openssl/openssl_missing.c +0 -66
  7. data/ext/openssl/openssl_missing.h +26 -45
  8. data/ext/openssl/ossl.c +128 -237
  9. data/ext/openssl/ossl.h +31 -12
  10. data/ext/openssl/ossl_asn1.c +26 -13
  11. data/ext/openssl/ossl_bn.c +213 -139
  12. data/ext/openssl/ossl_cipher.c +13 -14
  13. data/ext/openssl/ossl_config.c +412 -41
  14. data/ext/openssl/ossl_config.h +4 -7
  15. data/ext/openssl/ossl_digest.c +10 -10
  16. data/ext/openssl/ossl_engine.c +17 -16
  17. data/ext/openssl/ossl_hmac.c +57 -136
  18. data/ext/openssl/ossl_kdf.c +12 -4
  19. data/ext/openssl/ossl_ns_spki.c +1 -1
  20. data/ext/openssl/ossl_ocsp.c +11 -59
  21. data/ext/openssl/ossl_pkcs12.c +22 -4
  22. data/ext/openssl/ossl_pkcs7.c +45 -62
  23. data/ext/openssl/ossl_pkey.c +1320 -196
  24. data/ext/openssl/ossl_pkey.h +36 -73
  25. data/ext/openssl/ossl_pkey_dh.c +152 -347
  26. data/ext/openssl/ossl_pkey_dsa.c +157 -413
  27. data/ext/openssl/ossl_pkey_ec.c +227 -343
  28. data/ext/openssl/ossl_pkey_rsa.c +159 -491
  29. data/ext/openssl/ossl_provider.c +211 -0
  30. data/ext/openssl/ossl_provider.h +5 -0
  31. data/ext/openssl/ossl_ssl.c +530 -450
  32. data/ext/openssl/ossl_ssl_session.c +29 -30
  33. data/ext/openssl/ossl_ts.c +38 -23
  34. data/ext/openssl/ossl_x509.c +0 -6
  35. data/ext/openssl/ossl_x509attr.c +1 -1
  36. data/ext/openssl/ossl_x509cert.c +168 -12
  37. data/ext/openssl/ossl_x509crl.c +14 -11
  38. data/ext/openssl/ossl_x509ext.c +14 -9
  39. data/ext/openssl/ossl_x509name.c +10 -3
  40. data/ext/openssl/ossl_x509req.c +14 -11
  41. data/ext/openssl/ossl_x509revoked.c +4 -4
  42. data/ext/openssl/ossl_x509store.c +166 -75
  43. data/lib/openssl/buffering.rb +9 -3
  44. data/lib/openssl/digest.rb +1 -5
  45. data/lib/openssl/hmac.rb +65 -0
  46. data/lib/openssl/pkey.rb +429 -0
  47. data/lib/openssl/ssl.rb +22 -17
  48. data/lib/openssl/version.rb +1 -1
  49. data/lib/openssl/x509.rb +22 -0
  50. data/lib/openssl.rb +0 -1
  51. metadata +10 -79
  52. data/ext/openssl/ruby_missing.h +0 -24
  53. data/lib/openssl/config.rb +0 -501
@@ -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;
539
+ #ifdef HAVE_EVP_PKEY_CHECK
540
+ EVP_PKEY *pkey;
541
+ EVP_PKEY_CTX *pctx;
542
+ const EC_KEY *ec;
597
543
 
544
+ GetPKey(self, pkey);
598
545
  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 */
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
+ }
615
562
 
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
- {
563
+ EVP_PKEY_CTX_free(pctx);
564
+ #else
624
565
  EC_KEY *ec;
625
- unsigned int buf_len;
626
- VALUE str;
627
566
 
628
567
  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
- }
641
-
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
- {
650
- EC_KEY *ec;
568
+ if (EC_KEY_check_key(ec) != 1)
569
+ ossl_raise(eECError, "EC_KEY_check_key");
570
+ #endif
651
571
 
652
- GetEC(self, ec);
653
- StringValue(data);
654
- StringValue(sig);
655
-
656
- switch (ECDSA_verify(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
657
- (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), ec)) {
658
- case 1:
659
- return Qtrue;
660
- case 0:
661
- return Qfalse;
662
- default:
663
- ossl_raise(eECError, "ECDSA_verify");
664
- }
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
  }
@@ -1631,6 +1516,10 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
1631
1516
  if (EC_POINT_mul(group, point_result, bn_g, point_self, bn, ossl_bn_ctx) != 1)
1632
1517
  ossl_raise(eEC_POINT, NULL);
1633
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
1634
1523
  /*
1635
1524
  * bignums | arg1[0] | arg1[1] | arg1[2] | ...
1636
1525
  * points | self | arg2[0] | arg2[1] | ...
@@ -1645,6 +1534,9 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
1645
1534
  if (RARRAY_LEN(arg1) != RARRAY_LEN(arg2) + 1) /* arg2 must be 1 larger */
1646
1535
  ossl_raise(rb_eArgError, "bns must be 1 longer than points; see the documentation");
1647
1536
 
1537
+ rb_warning("OpenSSL::PKey::EC::Point#mul(ary, ary) is deprecated; " \
1538
+ "use #mul(bn) form instead");
1539
+
1648
1540
  num = RARRAY_LEN(arg1);
1649
1541
  bns_tmp = rb_ary_tmp_new(num);
1650
1542
  bignums = ALLOCV_N(const BIGNUM *, tmp_b, num);
@@ -1670,6 +1562,7 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
1670
1562
 
1671
1563
  ALLOCV_END(tmp_b);
1672
1564
  ALLOCV_END(tmp_p);
1565
+ #endif
1673
1566
  }
1674
1567
 
1675
1568
  return result;
@@ -1710,10 +1603,6 @@ void Init_ossl_ec(void)
1710
1603
 
1711
1604
  s_GFp = rb_intern("GFp");
1712
1605
  s_GF2m = rb_intern("GF2m");
1713
- s_GFp_simple = rb_intern("GFp_simple");
1714
- s_GFp_mont = rb_intern("GFp_mont");
1715
- s_GFp_nist = rb_intern("GFp_nist");
1716
- s_GF2m_simple = rb_intern("GF2m_simple");
1717
1606
 
1718
1607
  ID_uncompressed = rb_intern("uncompressed");
1719
1608
  ID_compressed = rb_intern("compressed");
@@ -1728,8 +1617,9 @@ void Init_ossl_ec(void)
1728
1617
 
1729
1618
  rb_define_singleton_method(cEC, "generate", ossl_ec_key_s_generate, 1);
1730
1619
  rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1);
1620
+ #ifndef HAVE_EVP_PKEY_DUP
1731
1621
  rb_define_method(cEC, "initialize_copy", ossl_ec_key_initialize_copy, 1);
1732
- /* copy/dup/cmp */
1622
+ #endif
1733
1623
 
1734
1624
  rb_define_method(cEC, "group", ossl_ec_key_get_group, 0);
1735
1625
  rb_define_method(cEC, "group=", ossl_ec_key_set_group, 1);
@@ -1752,15 +1642,9 @@ void Init_ossl_ec(void)
1752
1642
  rb_define_alias(cEC, "generate_key", "generate_key!");
1753
1643
  rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0);
1754
1644
 
1755
- rb_define_method(cEC, "dh_compute_key", ossl_ec_key_dh_compute_key, 1);
1756
- rb_define_method(cEC, "dsa_sign_asn1", ossl_ec_key_dsa_sign_asn1, 1);
1757
- rb_define_method(cEC, "dsa_verify_asn1", ossl_ec_key_dsa_verify_asn1, 2);
1758
- /* do_sign/do_verify */
1759
-
1760
1645
  rb_define_method(cEC, "export", ossl_ec_key_export, -1);
1761
1646
  rb_define_alias(cEC, "to_pem", "export");
1762
1647
  rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0);
1763
- rb_define_method(cEC, "to_text", ossl_ec_key_to_text, 0);
1764
1648
 
1765
1649
 
1766
1650
  rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc);