openssl 3.1.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +36 -27
  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 -44
  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 +10 -10
  40. data/lib/openssl/version.rb +1 -1
  41. data/lib/openssl/x509.rb +5 -5
  42. metadata +12 -7
@@ -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
  {
@@ -842,6 +972,12 @@ ossl_pkey_public_to_der(VALUE self)
842
972
  * pkey.public_to_pem -> string
843
973
  *
844
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-----
845
981
  */
846
982
  static VALUE
847
983
  ossl_pkey_public_to_pem(VALUE self)
@@ -849,6 +985,35 @@ ossl_pkey_public_to_pem(VALUE self)
849
985
  return ossl_pkey_export_spki(self, 0);
850
986
  }
851
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
+
852
1017
  /*
853
1018
  * call-seq:
854
1019
  * pkey.compare?(another_pkey) -> true | false
@@ -1586,6 +1751,10 @@ Init_ossl_pkey(void)
1586
1751
  rb_define_module_function(mPKey, "read", ossl_pkey_new_from_data, -1);
1587
1752
  rb_define_module_function(mPKey, "generate_parameters", ossl_pkey_s_generate_parameters, -1);
1588
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
1589
1758
 
1590
1759
  rb_define_alloc_func(cPKey, ossl_pkey_alloc);
1591
1760
  rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
@@ -1601,6 +1770,10 @@ Init_ossl_pkey(void)
1601
1770
  rb_define_method(cPKey, "private_to_pem", ossl_pkey_private_to_pem, -1);
1602
1771
  rb_define_method(cPKey, "public_to_der", ossl_pkey_public_to_der, 0);
1603
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
1604
1777
  rb_define_method(cPKey, "compare?", ossl_pkey_compare, 1);
1605
1778
 
1606
1779
  rb_define_method(cPKey, "sign", ossl_pkey_sign, -1);
@@ -216,9 +216,20 @@ ossl_dh_is_private(VALUE self)
216
216
  * dh.to_pem -> aString
217
217
  * dh.to_s -> aString
218
218
  *
219
- * Encodes this DH to its PEM encoding. Note that any existing per-session
220
- * public/private keys will *not* get encoded, just the Diffie-Hellman
221
- * parameters will be encoded.
219
+ * Serializes the DH parameters to a PEM-encoding.
220
+ *
221
+ * Note that any existing per-session public/private keys will *not* get
222
+ * encoded, just the Diffie-Hellman parameters will be encoded.
223
+ *
224
+ * PEM-encoded parameters will look like:
225
+ *
226
+ * -----BEGIN DH PARAMETERS-----
227
+ * [...]
228
+ * -----END DH PARAMETERS-----
229
+ *
230
+ * See also #public_to_pem (X.509 SubjectPublicKeyInfo) and
231
+ * #private_to_pem (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) for
232
+ * serialization with the private or public key components.
222
233
  */
223
234
  static VALUE
224
235
  ossl_dh_export(VALUE self)
@@ -244,10 +255,14 @@ ossl_dh_export(VALUE self)
244
255
  * call-seq:
245
256
  * dh.to_der -> aString
246
257
  *
247
- * Encodes this DH to its DER encoding. Note that any existing per-session
248
- * public/private keys will *not* get encoded, just the Diffie-Hellman
249
- * parameters will be encoded.
250
-
258
+ * Serializes the DH parameters to a DER-encoding
259
+ *
260
+ * Note that any existing per-session public/private keys will *not* get
261
+ * encoded, just the Diffie-Hellman parameters will be encoded.
262
+ *
263
+ * See also #public_to_der (X.509 SubjectPublicKeyInfo) and
264
+ * #private_to_der (PKCS #8 PrivateKeyInfo or EncryptedPrivateKeyInfo) for
265
+ * serialization with the private or public key components.
251
266
  */
252
267
  static VALUE
253
268
  ossl_dh_to_der(VALUE self)