openssl 3.1.2 → 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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +33 -41
  3. data/README.md +36 -19
  4. data/ext/openssl/extconf.rb +35 -8
  5. data/ext/openssl/ossl.c +73 -195
  6. data/ext/openssl/ossl.h +5 -6
  7. data/ext/openssl/ossl_asn1.c +24 -19
  8. data/ext/openssl/ossl_bn.c +1 -1
  9. data/ext/openssl/ossl_cipher.c +5 -20
  10. data/ext/openssl/ossl_config.c +1 -1
  11. data/ext/openssl/ossl_digest.c +1 -2
  12. data/ext/openssl/ossl_engine.c +1 -1
  13. data/ext/openssl/ossl_hmac.c +1 -1
  14. data/ext/openssl/ossl_kdf.c +1 -1
  15. data/ext/openssl/ossl_ns_spki.c +1 -1
  16. data/ext/openssl/ossl_ocsp.c +6 -6
  17. data/ext/openssl/ossl_pkcs12.c +1 -1
  18. data/ext/openssl/ossl_pkcs7.c +4 -14
  19. data/ext/openssl/ossl_pkey.c +217 -45
  20. data/ext/openssl/ossl_pkey_dh.c +22 -7
  21. data/ext/openssl/ossl_pkey_dsa.c +57 -8
  22. data/ext/openssl/ossl_pkey_ec.c +65 -9
  23. data/ext/openssl/ossl_pkey_rsa.c +68 -13
  24. data/ext/openssl/ossl_provider.c +211 -0
  25. data/ext/openssl/ossl_provider.h +5 -0
  26. data/ext/openssl/ossl_ssl.c +83 -65
  27. data/ext/openssl/ossl_ssl_session.c +1 -1
  28. data/ext/openssl/ossl_ts.c +3 -3
  29. data/ext/openssl/ossl_x509attr.c +1 -1
  30. data/ext/openssl/ossl_x509cert.c +1 -1
  31. data/ext/openssl/ossl_x509crl.c +1 -1
  32. data/ext/openssl/ossl_x509ext.c +13 -7
  33. data/ext/openssl/ossl_x509name.c +1 -1
  34. data/ext/openssl/ossl_x509req.c +1 -1
  35. data/ext/openssl/ossl_x509revoked.c +1 -1
  36. data/ext/openssl/ossl_x509store.c +12 -5
  37. data/lib/openssl/buffering.rb +8 -16
  38. data/lib/openssl/digest.rb +1 -5
  39. data/lib/openssl/ssl.rb +11 -10
  40. data/lib/openssl/version.rb +1 -1
  41. data/lib/openssl/x509.rb +5 -5
  42. metadata +12 -6
data/ext/openssl/ossl.h CHANGED
@@ -62,6 +62,10 @@
62
62
  # define OSSL_USE_ENGINE
63
63
  #endif
64
64
 
65
+ #if OSSL_OPENSSL_PREREQ(3, 0, 0)
66
+ # define OSSL_USE_PROVIDER
67
+ #endif
68
+
65
69
  /*
66
70
  * Common Module
67
71
  */
@@ -157,7 +161,6 @@ VALUE ossl_to_der_if_possible(VALUE);
157
161
  */
158
162
  extern VALUE dOSSL;
159
163
 
160
- #if defined(HAVE_VA_ARGS_MACRO)
161
164
  #define OSSL_Debug(...) do { \
162
165
  if (dOSSL == Qtrue) { \
163
166
  fprintf(stderr, "OSSL_DEBUG: "); \
@@ -166,11 +169,6 @@ extern VALUE dOSSL;
166
169
  } \
167
170
  } while (0)
168
171
 
169
- #else
170
- void ossl_debug(const char *, ...);
171
- #define OSSL_Debug ossl_debug
172
- #endif
173
-
174
172
  /*
175
173
  * Include all parts
176
174
  */
@@ -194,6 +192,7 @@ void ossl_debug(const char *, ...);
194
192
  #endif
195
193
  #include "ossl_x509.h"
196
194
  #include "ossl_engine.h"
195
+ #include "ossl_provider.h"
197
196
  #include "ossl_kdf.h"
198
197
 
199
198
  void Init_openssl(void);
@@ -1298,6 +1298,30 @@ ossl_asn1obj_get_ln(VALUE self)
1298
1298
  return ret;
1299
1299
  }
1300
1300
 
1301
+ /*
1302
+ * call-seq:
1303
+ * oid == other_oid => true or false
1304
+ *
1305
+ * Returns +true+ if _other_oid_ is the same as _oid_
1306
+ */
1307
+ static VALUE
1308
+ ossl_asn1obj_eq(VALUE self, VALUE other)
1309
+ {
1310
+ VALUE valSelf, valOther;
1311
+ int nidSelf, nidOther;
1312
+
1313
+ valSelf = ossl_asn1_get_value(self);
1314
+ valOther = ossl_asn1_get_value(other);
1315
+
1316
+ if ((nidSelf = OBJ_txt2nid(StringValueCStr(valSelf))) == NID_undef)
1317
+ ossl_raise(eASN1Error, "OBJ_txt2nid");
1318
+
1319
+ if ((nidOther = OBJ_txt2nid(StringValueCStr(valOther))) == NID_undef)
1320
+ ossl_raise(eASN1Error, "OBJ_txt2nid");
1321
+
1322
+ return nidSelf == nidOther ? Qtrue : Qfalse;
1323
+ }
1324
+
1301
1325
  static VALUE
1302
1326
  asn1obj_get_oid_i(VALUE vobj)
1303
1327
  {
@@ -1342,25 +1366,6 @@ ossl_asn1obj_get_oid(VALUE self)
1342
1366
  return str;
1343
1367
  }
1344
1368
 
1345
- /*
1346
- * call-seq:
1347
- * oid == other_oid => true or false
1348
- *
1349
- * Returns +true+ if _other_oid_ is the same as _oid_.
1350
- */
1351
- static VALUE
1352
- ossl_asn1obj_eq(VALUE self, VALUE other)
1353
- {
1354
- VALUE oid1, oid2;
1355
-
1356
- if (!rb_obj_is_kind_of(other, cASN1ObjectId))
1357
- return Qfalse;
1358
-
1359
- oid1 = ossl_asn1obj_get_oid(self);
1360
- oid2 = ossl_asn1obj_get_oid(other);
1361
- return rb_str_equal(oid1, oid2);
1362
- }
1363
-
1364
1369
  #define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \
1365
1370
  static VALUE ossl_asn1_##klass(int argc, VALUE *argv, VALUE self)\
1366
1371
  { return rb_funcall3(cASN1##klass, rb_intern("new"), argc, argv); }
@@ -41,7 +41,7 @@ static const rb_data_type_t ossl_bn_type = {
41
41
  {
42
42
  0, ossl_bn_free,
43
43
  },
44
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
44
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
45
45
  };
46
46
 
47
47
  /*
@@ -42,7 +42,7 @@ static const rb_data_type_t ossl_cipher_type = {
42
42
  {
43
43
  0, ossl_cipher_free,
44
44
  },
45
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
45
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
46
46
  };
47
47
 
48
48
  /*
@@ -386,37 +386,22 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
386
386
  in = (unsigned char *)RSTRING_PTR(data);
387
387
  in_len = RSTRING_LEN(data);
388
388
  GetCipher(self, ctx);
389
-
390
- /*
391
- * As of OpenSSL 3.2, there is no reliable way to determine the required
392
- * output buffer size for arbitrary cipher modes.
393
- * https://github.com/openssl/openssl/issues/22628
394
- *
395
- * in_len+block_size is usually sufficient, but AES key wrap with padding
396
- * ciphers require in_len+15 even though they have a block size of 8 bytes.
397
- *
398
- * Using EVP_MAX_BLOCK_LENGTH (32) as a safe upper bound for ciphers
399
- * currently implemented in OpenSSL, but this can change in the future.
400
- */
401
- if (in_len > LONG_MAX - EVP_MAX_BLOCK_LENGTH) {
389
+ out_len = in_len+EVP_CIPHER_CTX_block_size(ctx);
390
+ if (out_len <= 0) {
402
391
  ossl_raise(rb_eRangeError,
403
392
  "data too big to make output buffer: %ld bytes", in_len);
404
393
  }
405
- out_len = in_len + EVP_MAX_BLOCK_LENGTH;
406
394
 
407
395
  if (NIL_P(str)) {
408
396
  str = rb_str_new(0, out_len);
409
397
  } else {
410
398
  StringValue(str);
411
- if ((long)rb_str_capacity(str) >= out_len)
412
- rb_str_modify(str);
413
- else
414
- rb_str_modify_expand(str, out_len - RSTRING_LEN(str));
399
+ rb_str_resize(str, out_len);
415
400
  }
416
401
 
417
402
  if (!ossl_cipher_update_long(ctx, (unsigned char *)RSTRING_PTR(str), &out_len, in, in_len))
418
403
  ossl_raise(eCipherError, NULL);
419
- assert(out_len <= RSTRING_LEN(str));
404
+ assert(out_len < RSTRING_LEN(str));
420
405
  rb_str_set_len(str, out_len);
421
406
 
422
407
  return str;
@@ -22,7 +22,7 @@ static const rb_data_type_t ossl_config_type = {
22
22
  {
23
23
  0, nconf_free,
24
24
  },
25
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
25
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
26
26
  };
27
27
 
28
28
  CONF *
@@ -35,7 +35,7 @@ static const rb_data_type_t ossl_digest_type = {
35
35
  {
36
36
  0, ossl_digest_free,
37
37
  },
38
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
38
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
39
39
  };
40
40
 
41
41
  /*
@@ -232,7 +232,6 @@ ossl_digest_finish(int argc, VALUE *argv, VALUE self)
232
232
  str = rb_str_new(NULL, out_len);
233
233
  } else {
234
234
  StringValue(str);
235
- rb_str_modify(str);
236
235
  rb_str_resize(str, out_len);
237
236
  }
238
237
 
@@ -78,7 +78,7 @@ static const rb_data_type_t ossl_engine_type = {
78
78
  {
79
79
  0, ossl_engine_free,
80
80
  },
81
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
81
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
82
82
  };
83
83
 
84
84
  /*
@@ -42,7 +42,7 @@ static const rb_data_type_t ossl_hmac_type = {
42
42
  {
43
43
  0, ossl_hmac_free,
44
44
  },
45
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
45
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
46
46
  };
47
47
 
48
48
  static VALUE
@@ -21,7 +21,7 @@ static VALUE mKDF, eKDF;
21
21
  * (https://tools.ietf.org/html/rfc2898#section-5.2).
22
22
  *
23
23
  * === Parameters
24
- * pass :: The passphrase.
24
+ * pass :: The password.
25
25
  * salt :: The salt. Salts prevent attacks based on dictionaries of common
26
26
  * passwords and attacks based on rainbow tables. It is a public
27
27
  * value that can be safely stored along with the password (e.g.
@@ -50,7 +50,7 @@ static const rb_data_type_t ossl_netscape_spki_type = {
50
50
  {
51
51
  0, ossl_netscape_spki_free,
52
52
  },
53
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
53
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
54
54
  };
55
55
 
56
56
  static VALUE
@@ -86,7 +86,7 @@ static const rb_data_type_t ossl_ocsp_request_type = {
86
86
  {
87
87
  0, ossl_ocsp_request_free,
88
88
  },
89
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
89
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
90
90
  };
91
91
 
92
92
  static void
@@ -100,7 +100,7 @@ static const rb_data_type_t ossl_ocsp_response_type = {
100
100
  {
101
101
  0, ossl_ocsp_response_free,
102
102
  },
103
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
103
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
104
104
  };
105
105
 
106
106
  static void
@@ -114,7 +114,7 @@ static const rb_data_type_t ossl_ocsp_basicresp_type = {
114
114
  {
115
115
  0, ossl_ocsp_basicresp_free,
116
116
  },
117
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
117
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
118
118
  };
119
119
 
120
120
  static void
@@ -128,7 +128,7 @@ static const rb_data_type_t ossl_ocsp_singleresp_type = {
128
128
  {
129
129
  0, ossl_ocsp_singleresp_free,
130
130
  },
131
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
131
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
132
132
  };
133
133
 
134
134
  static void
@@ -142,7 +142,7 @@ static const rb_data_type_t ossl_ocsp_certid_type = {
142
142
  {
143
143
  0, ossl_ocsp_certid_free,
144
144
  },
145
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
145
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
146
146
  };
147
147
 
148
148
  /*
@@ -1701,7 +1701,7 @@ Init_ossl_ocsp(void)
1701
1701
  * require 'net/http'
1702
1702
  *
1703
1703
  * http_response =
1704
- * Net::HTTP.start ocsp_uri.hostname, ocsp.port do |http|
1704
+ * Net::HTTP.start ocsp_uri.hostname, ocsp_uri.port do |http|
1705
1705
  * http.post ocsp_uri.path, request.to_der,
1706
1706
  * 'content-type' => 'application/ocsp-request'
1707
1707
  * end
@@ -44,7 +44,7 @@ static const rb_data_type_t ossl_pkcs12_type = {
44
44
  {
45
45
  0, ossl_pkcs12_free,
46
46
  },
47
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
47
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
48
48
  };
49
49
 
50
50
  static VALUE
@@ -65,7 +65,7 @@ const rb_data_type_t ossl_pkcs7_type = {
65
65
  {
66
66
  0, ossl_pkcs7_free,
67
67
  },
68
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
68
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
69
69
  };
70
70
 
71
71
  static void
@@ -79,7 +79,7 @@ static const rb_data_type_t ossl_pkcs7_signer_info_type = {
79
79
  {
80
80
  0, ossl_pkcs7_signer_info_free,
81
81
  },
82
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
82
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
83
83
  };
84
84
 
85
85
  static void
@@ -93,7 +93,7 @@ static const rb_data_type_t ossl_pkcs7_recip_info_type = {
93
93
  {
94
94
  0, ossl_pkcs7_recip_info_free,
95
95
  },
96
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
96
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
97
97
  };
98
98
 
99
99
  /*
@@ -165,13 +165,7 @@ ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
165
165
  out = NULL;
166
166
  pkcs7 = SMIME_read_PKCS7(in, &out);
167
167
  BIO_free(in);
168
- if (!pkcs7)
169
- ossl_raise(ePKCS7Error, "Could not parse the PKCS7");
170
- if (!pkcs7->d.ptr) {
171
- PKCS7_free(pkcs7);
172
- ossl_raise(ePKCS7Error, "No content in PKCS7");
173
- }
174
-
168
+ if(!pkcs7) ossl_raise(ePKCS7Error, NULL);
175
169
  data = out ? ossl_membio2str(out) : Qnil;
176
170
  SetPKCS7(ret, pkcs7);
177
171
  ossl_pkcs7_set_data(ret, data);
@@ -352,10 +346,6 @@ ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
352
346
  BIO_free(in);
353
347
  if (!p7)
354
348
  ossl_raise(rb_eArgError, "Could not parse the PKCS7");
355
- if (!p7->d.ptr) {
356
- PKCS7_free(p7);
357
- ossl_raise(rb_eArgError, "No content in PKCS7");
358
- }
359
349
 
360
350
  RTYPEDDATA_DATA(self) = p7;
361
351
  PKCS7_free(p7_orig);
@@ -35,7 +35,7 @@ const rb_data_type_t ossl_evp_pkey_type = {
35
35
  {
36
36
  0, ossl_evp_pkey_free,
37
37
  },
38
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
38
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
39
39
  };
40
40
 
41
41
  static VALUE
@@ -82,31 +82,62 @@ ossl_pkey_new(EVP_PKEY *pkey)
82
82
  #if OSSL_OPENSSL_PREREQ(3, 0, 0)
83
83
  # include <openssl/decoder.h>
84
84
 
85
- EVP_PKEY *
86
- ossl_pkey_read_generic(BIO *bio, VALUE pass)
85
+ static EVP_PKEY *
86
+ ossl_pkey_read(BIO *bio, const char *input_type, int selection, VALUE pass)
87
87
  {
88
88
  void *ppass = (void *)pass;
89
89
  OSSL_DECODER_CTX *dctx;
90
90
  EVP_PKEY *pkey = NULL;
91
91
  int pos = 0, pos2;
92
92
 
93
- dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", NULL, NULL, 0, NULL, NULL);
93
+ dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, input_type, NULL, NULL,
94
+ selection, NULL, NULL);
94
95
  if (!dctx)
95
96
  goto out;
96
- if (OSSL_DECODER_CTX_set_pem_password_cb(dctx, ossl_pem_passwd_cb, ppass) != 1)
97
- goto out;
98
-
99
- /* First check DER */
100
- if (OSSL_DECODER_from_bio(dctx, bio) == 1)
97
+ if (OSSL_DECODER_CTX_set_pem_password_cb(dctx, ossl_pem_passwd_cb,
98
+ ppass) != 1)
101
99
  goto out;
100
+ while (1) {
101
+ if (OSSL_DECODER_from_bio(dctx, bio) == 1)
102
+ goto out;
103
+ if (BIO_eof(bio))
104
+ break;
105
+ pos2 = BIO_tell(bio);
106
+ if (pos2 < 0 || pos2 <= pos)
107
+ break;
108
+ ossl_clear_error();
109
+ pos = pos2;
110
+ }
111
+ out:
102
112
  OSSL_BIO_reset(bio);
113
+ OSSL_DECODER_CTX_free(dctx);
114
+ return pkey;
115
+ }
103
116
 
104
- /* Then check PEM; multiple OSSL_DECODER_from_bio() calls may be needed */
105
- if (OSSL_DECODER_CTX_set_input_type(dctx, "PEM") != 1)
106
- goto out;
117
+ EVP_PKEY *
118
+ ossl_pkey_read_generic(BIO *bio, VALUE pass)
119
+ {
120
+ EVP_PKEY *pkey = NULL;
121
+ /* First check DER, then check PEM. */
122
+ const char *input_types[] = {"DER", "PEM"};
123
+ int input_type_num = (int)(sizeof(input_types) / sizeof(char *));
107
124
  /*
108
- * First check for private key formats. This is to keep compatibility with
109
- * ruby/openssl < 3.0 which decoded the following as a private key.
125
+ * Non-zero selections to try to decode.
126
+ *
127
+ * See EVP_PKEY_fromdata(3) - Selections to see all the selections.
128
+ *
129
+ * This is a workaround for the decoder failing to decode or returning
130
+ * bogus keys with selection 0, if a key management provider is different
131
+ * from a decoder provider. The workaround is to avoid using selection 0.
132
+ *
133
+ * Affected OpenSSL versions: >= 3.1.0, <= 3.1.2, or >= 3.0.0, <= 3.0.10
134
+ * Fixed OpenSSL versions: 3.2, next release of the 3.1.z and 3.0.z
135
+ *
136
+ * See https://github.com/openssl/openssl/pull/21519 for details.
137
+ *
138
+ * First check for private key formats (EVP_PKEY_KEYPAIR). This is to keep
139
+ * compatibility with ruby/openssl < 3.0 which decoded the following as a
140
+ * private key.
110
141
  *
111
142
  * $ openssl ecparam -name prime256v1 -genkey -outform PEM
112
143
  * -----BEGIN EC PARAMETERS-----
@@ -124,36 +155,28 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass)
124
155
  *
125
156
  * Note that normally, the input is supposed to contain a single decodable
126
157
  * PEM block only, so this special handling should not create a new problem.
158
+ *
159
+ * Note that we need to create the OSSL_DECODER_CTX variable each time when
160
+ * we use the different selection as a workaround.
161
+ * See https://github.com/openssl/openssl/issues/20657 for details.
127
162
  */
128
- OSSL_DECODER_CTX_set_selection(dctx, EVP_PKEY_KEYPAIR);
129
- while (1) {
130
- if (OSSL_DECODER_from_bio(dctx, bio) == 1)
131
- goto out;
132
- if (BIO_eof(bio))
133
- break;
134
- pos2 = BIO_tell(bio);
135
- if (pos2 < 0 || pos2 <= pos)
136
- break;
137
- ossl_clear_error();
138
- pos = pos2;
139
- }
140
-
141
- OSSL_BIO_reset(bio);
142
- OSSL_DECODER_CTX_set_selection(dctx, 0);
143
- while (1) {
144
- if (OSSL_DECODER_from_bio(dctx, bio) == 1)
145
- goto out;
146
- if (BIO_eof(bio))
147
- break;
148
- pos2 = BIO_tell(bio);
149
- if (pos2 < 0 || pos2 <= pos)
150
- break;
151
- ossl_clear_error();
152
- pos = pos2;
163
+ int selections[] = {
164
+ EVP_PKEY_KEYPAIR,
165
+ EVP_PKEY_KEY_PARAMETERS,
166
+ EVP_PKEY_PUBLIC_KEY
167
+ };
168
+ int selection_num = (int)(sizeof(selections) / sizeof(int));
169
+ int i, j;
170
+
171
+ for (i = 0; i < input_type_num; i++) {
172
+ for (j = 0; j < selection_num; j++) {
173
+ pkey = ossl_pkey_read(bio, input_types[i], selections[j], pass);
174
+ if (pkey) {
175
+ goto out;
176
+ }
177
+ }
153
178
  }
154
-
155
179
  out:
156
- OSSL_DECODER_CTX_free(dctx);
157
180
  return pkey;
158
181
  }
159
182
  #else
@@ -260,9 +283,9 @@ struct pkey_blocking_generate_arg {
260
283
  EVP_PKEY_CTX *ctx;
261
284
  EVP_PKEY *pkey;
262
285
  int state;
263
- int yield: 1;
264
- int genparam: 1;
265
- int interrupted: 1;
286
+ unsigned int yield: 1;
287
+ unsigned int genparam: 1;
288
+ unsigned int interrupted: 1;
266
289
  };
267
290
 
268
291
  static VALUE
@@ -612,6 +635,72 @@ ossl_pkey_initialize_copy(VALUE self, VALUE other)
612
635
  }
613
636
  #endif
614
637
 
638
+ #ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
639
+ /*
640
+ * call-seq:
641
+ * OpenSSL::PKey.new_raw_private_key(algo, string) -> PKey
642
+ *
643
+ * See the OpenSSL documentation for EVP_PKEY_new_raw_private_key()
644
+ */
645
+
646
+ static VALUE
647
+ ossl_pkey_new_raw_private_key(VALUE self, VALUE type, VALUE key)
648
+ {
649
+ EVP_PKEY *pkey;
650
+ const EVP_PKEY_ASN1_METHOD *ameth;
651
+ int pkey_id;
652
+ size_t keylen;
653
+
654
+ StringValue(type);
655
+ StringValue(key);
656
+ ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type));
657
+ if (!ameth)
658
+ ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type);
659
+ EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
660
+
661
+ keylen = RSTRING_LEN(key);
662
+
663
+ pkey = EVP_PKEY_new_raw_private_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen);
664
+ if (!pkey)
665
+ ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key");
666
+
667
+ return ossl_pkey_new(pkey);
668
+ }
669
+ #endif
670
+
671
+ #ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
672
+ /*
673
+ * call-seq:
674
+ * OpenSSL::PKey.new_raw_public_key(algo, string) -> PKey
675
+ *
676
+ * See the OpenSSL documentation for EVP_PKEY_new_raw_public_key()
677
+ */
678
+
679
+ static VALUE
680
+ ossl_pkey_new_raw_public_key(VALUE self, VALUE type, VALUE key)
681
+ {
682
+ EVP_PKEY *pkey;
683
+ const EVP_PKEY_ASN1_METHOD *ameth;
684
+ int pkey_id;
685
+ size_t keylen;
686
+
687
+ StringValue(type);
688
+ StringValue(key);
689
+ ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type));
690
+ if (!ameth)
691
+ ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type);
692
+ EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
693
+
694
+ keylen = RSTRING_LEN(key);
695
+
696
+ pkey = EVP_PKEY_new_raw_public_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen);
697
+ if (!pkey)
698
+ ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key");
699
+
700
+ return ossl_pkey_new(pkey);
701
+ }
702
+ #endif
703
+
615
704
  /*
616
705
  * call-seq:
617
706
  * pkey.oid -> string
@@ -793,6 +882,18 @@ ossl_pkey_private_to_der(int argc, VALUE *argv, VALUE self)
793
882
  *
794
883
  * Serializes the private key to PEM-encoded PKCS #8 format. See #private_to_der
795
884
  * for more details.
885
+ *
886
+ * An unencrypted PEM-encoded key will look like:
887
+ *
888
+ * -----BEGIN PRIVATE KEY-----
889
+ * [...]
890
+ * -----END PRIVATE KEY-----
891
+ *
892
+ * An encrypted PEM-encoded key will look like:
893
+ *
894
+ * -----BEGIN ENCRYPTED PRIVATE KEY-----
895
+ * [...]
896
+ * -----END ENCRYPTED PRIVATE KEY-----
796
897
  */
797
898
  static VALUE
798
899
  ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self)
@@ -800,6 +901,35 @@ ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self)
800
901
  return do_pkcs8_export(argc, argv, self, 0);
801
902
  }
802
903
 
904
+ #ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
905
+ /*
906
+ * call-seq:
907
+ * pkey.raw_private_key => string
908
+ *
909
+ * See the OpenSSL documentation for EVP_PKEY_get_raw_private_key()
910
+ */
911
+
912
+ static VALUE
913
+ ossl_pkey_raw_private_key(VALUE self)
914
+ {
915
+ EVP_PKEY *pkey;
916
+ VALUE str;
917
+ size_t len;
918
+
919
+ GetPKey(self, pkey);
920
+ if (EVP_PKEY_get_raw_private_key(pkey, NULL, &len) != 1)
921
+ ossl_raise(ePKeyError, "EVP_PKEY_get_raw_private_key");
922
+ str = rb_str_new(NULL, len);
923
+
924
+ if (EVP_PKEY_get_raw_private_key(pkey, (unsigned char *)RSTRING_PTR(str), &len) != 1)
925
+ ossl_raise(ePKeyError, "EVP_PKEY_get_raw_private_key");
926
+
927
+ rb_str_set_len(str, len);
928
+
929
+ return str;
930
+ }
931
+ #endif
932
+
803
933
  VALUE
804
934
  ossl_pkey_export_spki(VALUE self, int to_der)
805
935
  {
@@ -807,7 +937,6 @@ ossl_pkey_export_spki(VALUE self, int to_der)
807
937
  BIO *bio;
808
938
 
809
939
  GetPKey(self, pkey);
810
- ossl_pkey_check_public_key(pkey);
811
940
  bio = BIO_new(BIO_s_mem());
812
941
  if (!bio)
813
942
  ossl_raise(ePKeyError, "BIO_new");
@@ -843,6 +972,12 @@ ossl_pkey_public_to_der(VALUE self)
843
972
  * pkey.public_to_pem -> string
844
973
  *
845
974
  * Serializes the public key to PEM-encoded X.509 SubjectPublicKeyInfo format.
975
+ *
976
+ * A PEM-encoded key will look like:
977
+ *
978
+ * -----BEGIN PUBLIC KEY-----
979
+ * [...]
980
+ * -----END PUBLIC KEY-----
846
981
  */
847
982
  static VALUE
848
983
  ossl_pkey_public_to_pem(VALUE self)
@@ -850,6 +985,35 @@ ossl_pkey_public_to_pem(VALUE self)
850
985
  return ossl_pkey_export_spki(self, 0);
851
986
  }
852
987
 
988
+ #ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
989
+ /*
990
+ * call-seq:
991
+ * pkey.raw_public_key => string
992
+ *
993
+ * See the OpenSSL documentation for EVP_PKEY_get_raw_public_key()
994
+ */
995
+
996
+ static VALUE
997
+ ossl_pkey_raw_public_key(VALUE self)
998
+ {
999
+ EVP_PKEY *pkey;
1000
+ VALUE str;
1001
+ size_t len;
1002
+
1003
+ GetPKey(self, pkey);
1004
+ if (EVP_PKEY_get_raw_public_key(pkey, NULL, &len) != 1)
1005
+ ossl_raise(ePKeyError, "EVP_PKEY_get_raw_public_key");
1006
+ str = rb_str_new(NULL, len);
1007
+
1008
+ if (EVP_PKEY_get_raw_public_key(pkey, (unsigned char *)RSTRING_PTR(str), &len) != 1)
1009
+ ossl_raise(ePKeyError, "EVP_PKEY_get_raw_public_key");
1010
+
1011
+ rb_str_set_len(str, len);
1012
+
1013
+ return str;
1014
+ }
1015
+ #endif
1016
+
853
1017
  /*
854
1018
  * call-seq:
855
1019
  * pkey.compare?(another_pkey) -> true | false
@@ -1587,6 +1751,10 @@ Init_ossl_pkey(void)
1587
1751
  rb_define_module_function(mPKey, "read", ossl_pkey_new_from_data, -1);
1588
1752
  rb_define_module_function(mPKey, "generate_parameters", ossl_pkey_s_generate_parameters, -1);
1589
1753
  rb_define_module_function(mPKey, "generate_key", ossl_pkey_s_generate_key, -1);
1754
+ #ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
1755
+ rb_define_module_function(mPKey, "new_raw_private_key", ossl_pkey_new_raw_private_key, 2);
1756
+ rb_define_module_function(mPKey, "new_raw_public_key", ossl_pkey_new_raw_public_key, 2);
1757
+ #endif
1590
1758
 
1591
1759
  rb_define_alloc_func(cPKey, ossl_pkey_alloc);
1592
1760
  rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
@@ -1602,6 +1770,10 @@ Init_ossl_pkey(void)
1602
1770
  rb_define_method(cPKey, "private_to_pem", ossl_pkey_private_to_pem, -1);
1603
1771
  rb_define_method(cPKey, "public_to_der", ossl_pkey_public_to_der, 0);
1604
1772
  rb_define_method(cPKey, "public_to_pem", ossl_pkey_public_to_pem, 0);
1773
+ #ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
1774
+ rb_define_method(cPKey, "raw_private_key", ossl_pkey_raw_private_key, 0);
1775
+ rb_define_method(cPKey, "raw_public_key", ossl_pkey_raw_public_key, 0);
1776
+ #endif
1605
1777
  rb_define_method(cPKey, "compare?", ossl_pkey_compare, 1);
1606
1778
 
1607
1779
  rb_define_method(cPKey, "sign", ossl_pkey_sign, -1);