openssl 2.1.3 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +35 -45
  3. data/History.md +302 -1
  4. data/README.md +2 -2
  5. data/ext/openssl/extconf.rb +77 -62
  6. data/ext/openssl/openssl_missing.c +0 -66
  7. data/ext/openssl/openssl_missing.h +59 -43
  8. data/ext/openssl/ossl.c +110 -64
  9. data/ext/openssl/ossl.h +33 -10
  10. data/ext/openssl/ossl_asn1.c +51 -13
  11. data/ext/openssl/ossl_bn.c +275 -146
  12. data/ext/openssl/ossl_bn.h +2 -1
  13. data/ext/openssl/ossl_cipher.c +39 -31
  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 +25 -60
  17. data/ext/openssl/ossl_engine.c +18 -27
  18. data/ext/openssl/ossl_hmac.c +60 -145
  19. data/ext/openssl/ossl_kdf.c +14 -22
  20. data/ext/openssl/ossl_ns_spki.c +1 -1
  21. data/ext/openssl/ossl_ocsp.c +11 -64
  22. data/ext/openssl/ossl_ocsp.h +3 -3
  23. data/ext/openssl/ossl_pkcs12.c +21 -3
  24. data/ext/openssl/ossl_pkcs7.c +45 -78
  25. data/ext/openssl/ossl_pkcs7.h +16 -0
  26. data/ext/openssl/ossl_pkey.c +1295 -178
  27. data/ext/openssl/ossl_pkey.h +36 -73
  28. data/ext/openssl/ossl_pkey_dh.c +130 -340
  29. data/ext/openssl/ossl_pkey_dsa.c +100 -405
  30. data/ext/openssl/ossl_pkey_ec.c +192 -335
  31. data/ext/openssl/ossl_pkey_rsa.c +110 -489
  32. data/ext/openssl/ossl_rand.c +2 -32
  33. data/ext/openssl/ossl_ssl.c +556 -442
  34. data/ext/openssl/ossl_ssl_session.c +28 -29
  35. data/ext/openssl/ossl_ts.c +1539 -0
  36. data/ext/openssl/ossl_ts.h +16 -0
  37. data/ext/openssl/ossl_x509.c +0 -6
  38. data/ext/openssl/ossl_x509cert.c +169 -13
  39. data/ext/openssl/ossl_x509crl.c +13 -10
  40. data/ext/openssl/ossl_x509ext.c +15 -2
  41. data/ext/openssl/ossl_x509name.c +15 -4
  42. data/ext/openssl/ossl_x509req.c +13 -10
  43. data/ext/openssl/ossl_x509revoked.c +3 -3
  44. data/ext/openssl/ossl_x509store.c +154 -70
  45. data/lib/openssl/bn.rb +1 -1
  46. data/lib/openssl/buffering.rb +37 -5
  47. data/lib/openssl/cipher.rb +1 -1
  48. data/lib/openssl/digest.rb +10 -12
  49. data/lib/openssl/hmac.rb +78 -0
  50. data/lib/openssl/marshal.rb +30 -0
  51. data/lib/openssl/pkcs5.rb +1 -1
  52. data/lib/openssl/pkey.rb +447 -1
  53. data/lib/openssl/ssl.rb +52 -9
  54. data/lib/openssl/version.rb +5 -0
  55. data/lib/openssl/x509.rb +177 -1
  56. data/lib/openssl.rb +24 -9
  57. metadata +10 -79
  58. data/ext/openssl/deprecation.rb +0 -27
  59. data/ext/openssl/ossl_version.h +0 -15
  60. data/ext/openssl/ruby_missing.h +0 -24
  61. data/lib/openssl/config.rb +0 -492
@@ -9,6 +9,10 @@
9
9
  */
10
10
  #include "ossl.h"
11
11
 
12
+ #ifdef OSSL_USE_ENGINE
13
+ # include <openssl/engine.h>
14
+ #endif
15
+
12
16
  /*
13
17
  * Classes
14
18
  */
@@ -17,64 +21,6 @@ VALUE cPKey;
17
21
  VALUE ePKeyError;
18
22
  static ID id_private_q;
19
23
 
20
- /*
21
- * callback for generating keys
22
- */
23
- static VALUE
24
- call_check_ints0(VALUE arg)
25
- {
26
- rb_thread_check_ints();
27
- return Qnil;
28
- }
29
-
30
- static void *
31
- call_check_ints(void *arg)
32
- {
33
- int state;
34
- rb_protect(call_check_ints0, Qnil, &state);
35
- return (void *)(VALUE)state;
36
- }
37
-
38
- int
39
- ossl_generate_cb_2(int p, int n, BN_GENCB *cb)
40
- {
41
- VALUE ary;
42
- struct ossl_generate_cb_arg *arg;
43
- int state;
44
-
45
- arg = (struct ossl_generate_cb_arg *)BN_GENCB_get_arg(cb);
46
- if (arg->yield) {
47
- ary = rb_ary_new2(2);
48
- rb_ary_store(ary, 0, INT2NUM(p));
49
- rb_ary_store(ary, 1, INT2NUM(n));
50
-
51
- /*
52
- * can be break by raising exception or 'break'
53
- */
54
- rb_protect(rb_yield, ary, &state);
55
- if (state) {
56
- arg->state = state;
57
- return 0;
58
- }
59
- }
60
- if (arg->interrupted) {
61
- arg->interrupted = 0;
62
- state = (int)(VALUE)rb_thread_call_with_gvl(call_check_ints, NULL);
63
- if (state) {
64
- arg->state = state;
65
- return 0;
66
- }
67
- }
68
- return 1;
69
- }
70
-
71
- void
72
- ossl_generate_cb_stop(void *ptr)
73
- {
74
- struct ossl_generate_cb_arg *arg = (struct ossl_generate_cb_arg *)ptr;
75
- arg->interrupted = 1;
76
- }
77
-
78
24
  static void
79
25
  ossl_evp_pkey_free(void *ptr)
80
26
  {
@@ -93,36 +39,29 @@ const rb_data_type_t ossl_evp_pkey_type = {
93
39
  };
94
40
 
95
41
  static VALUE
96
- pkey_new0(EVP_PKEY *pkey)
42
+ pkey_new0(VALUE arg)
97
43
  {
98
- VALUE obj;
99
- int type;
44
+ EVP_PKEY *pkey = (EVP_PKEY *)arg;
45
+ VALUE klass, obj;
100
46
 
101
- if (!pkey || (type = EVP_PKEY_base_id(pkey)) == EVP_PKEY_NONE)
102
- ossl_raise(rb_eRuntimeError, "pkey is empty");
103
-
104
- switch (type) {
47
+ switch (EVP_PKEY_base_id(pkey)) {
105
48
  #if !defined(OPENSSL_NO_RSA)
106
- case EVP_PKEY_RSA:
107
- return ossl_rsa_new(pkey);
49
+ case EVP_PKEY_RSA: klass = cRSA; break;
108
50
  #endif
109
51
  #if !defined(OPENSSL_NO_DSA)
110
- case EVP_PKEY_DSA:
111
- return ossl_dsa_new(pkey);
52
+ case EVP_PKEY_DSA: klass = cDSA; break;
112
53
  #endif
113
54
  #if !defined(OPENSSL_NO_DH)
114
- case EVP_PKEY_DH:
115
- return ossl_dh_new(pkey);
55
+ case EVP_PKEY_DH: klass = cDH; break;
116
56
  #endif
117
57
  #if !defined(OPENSSL_NO_EC)
118
- case EVP_PKEY_EC:
119
- return ossl_ec_new(pkey);
58
+ case EVP_PKEY_EC: klass = cEC; break;
120
59
  #endif
121
- default:
122
- obj = NewPKey(cPKey);
123
- SetPKey(obj, pkey);
124
- return obj;
60
+ default: klass = cPKey; break;
125
61
  }
62
+ obj = rb_obj_alloc(klass);
63
+ RTYPEDDATA_DATA(obj) = pkey;
64
+ return obj;
126
65
  }
127
66
 
128
67
  VALUE
@@ -131,7 +70,7 @@ ossl_pkey_new(EVP_PKEY *pkey)
131
70
  VALUE obj;
132
71
  int status;
133
72
 
134
- obj = rb_protect((VALUE (*)(VALUE))pkey_new0, (VALUE)pkey, &status);
73
+ obj = rb_protect(pkey_new0, (VALUE)pkey, &status);
135
74
  if (status) {
136
75
  EVP_PKEY_free(pkey);
137
76
  rb_jump_tag(status);
@@ -140,6 +79,114 @@ ossl_pkey_new(EVP_PKEY *pkey)
140
79
  return obj;
141
80
  }
142
81
 
82
+ #if OSSL_OPENSSL_PREREQ(3, 0, 0)
83
+ # include <openssl/decoder.h>
84
+
85
+ EVP_PKEY *
86
+ ossl_pkey_read_generic(BIO *bio, VALUE pass)
87
+ {
88
+ void *ppass = (void *)pass;
89
+ OSSL_DECODER_CTX *dctx;
90
+ EVP_PKEY *pkey = NULL;
91
+ int pos = 0, pos2;
92
+
93
+ dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", NULL, NULL, 0, NULL, NULL);
94
+ if (!dctx)
95
+ 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)
101
+ goto out;
102
+ OSSL_BIO_reset(bio);
103
+
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;
107
+ /*
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.
110
+ *
111
+ * $ openssl ecparam -name prime256v1 -genkey -outform PEM
112
+ * -----BEGIN EC PARAMETERS-----
113
+ * BggqhkjOPQMBBw==
114
+ * -----END EC PARAMETERS-----
115
+ * -----BEGIN EC PRIVATE KEY-----
116
+ * MHcCAQEEIAG8ugBbA5MHkqnZ9ujQF93OyUfL9tk8sxqM5Wv5tKg5oAoGCCqGSM49
117
+ * AwEHoUQDQgAEVcjhJfkwqh5C7kGuhAf8XaAjVuG5ADwb5ayg/cJijCgs+GcXeedj
118
+ * 86avKpGH84DXUlB23C/kPt+6fXYlitUmXQ==
119
+ * -----END EC PRIVATE KEY-----
120
+ *
121
+ * While the first PEM block is a proper encoding of ECParameters, thus
122
+ * OSSL_DECODER_from_bio() would pick it up, ruby/openssl used to return
123
+ * the latter instead. Existing applications expect this behavior.
124
+ *
125
+ * Note that normally, the input is supposed to contain a single decodable
126
+ * PEM block only, so this special handling should not create a new problem.
127
+ */
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;
153
+ }
154
+
155
+ out:
156
+ OSSL_DECODER_CTX_free(dctx);
157
+ return pkey;
158
+ }
159
+ #else
160
+ EVP_PKEY *
161
+ ossl_pkey_read_generic(BIO *bio, VALUE pass)
162
+ {
163
+ void *ppass = (void *)pass;
164
+ EVP_PKEY *pkey;
165
+
166
+ if ((pkey = d2i_PrivateKey_bio(bio, NULL)))
167
+ goto out;
168
+ OSSL_BIO_reset(bio);
169
+ if ((pkey = d2i_PKCS8PrivateKey_bio(bio, NULL, ossl_pem_passwd_cb, ppass)))
170
+ goto out;
171
+ OSSL_BIO_reset(bio);
172
+ if ((pkey = d2i_PUBKEY_bio(bio, NULL)))
173
+ goto out;
174
+ OSSL_BIO_reset(bio);
175
+ /* PEM_read_bio_PrivateKey() also parses PKCS #8 formats */
176
+ if ((pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, ppass)))
177
+ goto out;
178
+ OSSL_BIO_reset(bio);
179
+ if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)))
180
+ goto out;
181
+ OSSL_BIO_reset(bio);
182
+ if ((pkey = PEM_read_bio_Parameters(bio, NULL)))
183
+ goto out;
184
+
185
+ out:
186
+ return pkey;
187
+ }
188
+ #endif
189
+
143
190
  /*
144
191
  * call-seq:
145
192
  * OpenSSL::PKey.read(string [, pwd ]) -> PKey
@@ -149,7 +196,7 @@ ossl_pkey_new(EVP_PKEY *pkey)
149
196
  * instance of the appropriate PKey class.
150
197
  *
151
198
  * === Parameters
152
- * * _string+ is a DER- or PEM-encoded string containing an arbitrary private
199
+ * * _string_ is a DER- or PEM-encoded string containing an arbitrary private
153
200
  * or public key.
154
201
  * * _io_ is an instance of IO containing a DER- or PEM-encoded
155
202
  * arbitrary private or public key.
@@ -164,30 +211,283 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
164
211
  VALUE data, pass;
165
212
 
166
213
  rb_scan_args(argc, argv, "11", &data, &pass);
167
- pass = ossl_pem_passwd_value(pass);
168
-
169
214
  bio = ossl_obj2bio(&data);
170
- if (!(pkey = d2i_PrivateKey_bio(bio, NULL))) {
171
- OSSL_BIO_reset(bio);
172
- if (!(pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, (void *)pass))) {
173
- OSSL_BIO_reset(bio);
174
- if (!(pkey = d2i_PUBKEY_bio(bio, NULL))) {
175
- OSSL_BIO_reset(bio);
176
- pkey = PEM_read_bio_PUBKEY(bio, NULL, ossl_pem_passwd_cb, (void *)pass);
177
- }
178
- }
179
- }
180
-
215
+ pkey = ossl_pkey_read_generic(bio, ossl_pem_passwd_value(pass));
181
216
  BIO_free(bio);
182
217
  if (!pkey)
183
218
  ossl_raise(ePKeyError, "Could not parse PKey");
184
-
185
219
  return ossl_pkey_new(pkey);
186
220
  }
187
221
 
222
+ static VALUE
223
+ pkey_ctx_apply_options_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, ctx_v))
224
+ {
225
+ VALUE key = rb_ary_entry(i, 0), value = rb_ary_entry(i, 1);
226
+ EVP_PKEY_CTX *ctx = (EVP_PKEY_CTX *)ctx_v;
227
+
228
+ if (SYMBOL_P(key))
229
+ key = rb_sym2str(key);
230
+ value = rb_String(value);
231
+
232
+ if (EVP_PKEY_CTX_ctrl_str(ctx, StringValueCStr(key), StringValueCStr(value)) <= 0)
233
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_ctrl_str(ctx, %+"PRIsVALUE", %+"PRIsVALUE")",
234
+ key, value);
235
+ return Qnil;
236
+ }
237
+
238
+ static VALUE
239
+ pkey_ctx_apply_options0(VALUE args_v)
240
+ {
241
+ VALUE *args = (VALUE *)args_v;
242
+ Check_Type(args[1], T_HASH);
243
+
244
+ rb_block_call(args[1], rb_intern("each"), 0, NULL,
245
+ pkey_ctx_apply_options_i, args[0]);
246
+ return Qnil;
247
+ }
248
+
249
+ static void
250
+ pkey_ctx_apply_options(EVP_PKEY_CTX *ctx, VALUE options, int *state)
251
+ {
252
+ VALUE args[2];
253
+ args[0] = (VALUE)ctx;
254
+ args[1] = options;
255
+
256
+ rb_protect(pkey_ctx_apply_options0, (VALUE)args, state);
257
+ }
258
+
259
+ struct pkey_blocking_generate_arg {
260
+ EVP_PKEY_CTX *ctx;
261
+ EVP_PKEY *pkey;
262
+ int state;
263
+ int yield: 1;
264
+ int genparam: 1;
265
+ int interrupted: 1;
266
+ };
267
+
268
+ static VALUE
269
+ pkey_gen_cb_yield(VALUE ctx_v)
270
+ {
271
+ EVP_PKEY_CTX *ctx = (void *)ctx_v;
272
+ int i, info_num;
273
+ VALUE *argv;
274
+
275
+ info_num = EVP_PKEY_CTX_get_keygen_info(ctx, -1);
276
+ argv = ALLOCA_N(VALUE, info_num);
277
+ for (i = 0; i < info_num; i++)
278
+ argv[i] = INT2NUM(EVP_PKEY_CTX_get_keygen_info(ctx, i));
279
+
280
+ return rb_yield_values2(info_num, argv);
281
+ }
282
+
283
+ static VALUE
284
+ call_check_ints0(VALUE arg)
285
+ {
286
+ rb_thread_check_ints();
287
+ return Qnil;
288
+ }
289
+
290
+ static void *
291
+ call_check_ints(void *arg)
292
+ {
293
+ int state;
294
+ rb_protect(call_check_ints0, Qnil, &state);
295
+ return (void *)(VALUE)state;
296
+ }
297
+
298
+ static int
299
+ pkey_gen_cb(EVP_PKEY_CTX *ctx)
300
+ {
301
+ struct pkey_blocking_generate_arg *arg = EVP_PKEY_CTX_get_app_data(ctx);
302
+ int state;
303
+
304
+ if (arg->yield) {
305
+ rb_protect(pkey_gen_cb_yield, (VALUE)ctx, &state);
306
+ if (state) {
307
+ arg->state = state;
308
+ return 0;
309
+ }
310
+ }
311
+ if (arg->interrupted) {
312
+ arg->interrupted = 0;
313
+ state = (int)(VALUE)rb_thread_call_with_gvl(call_check_ints, NULL);
314
+ if (state) {
315
+ arg->state = state;
316
+ return 0;
317
+ }
318
+ }
319
+ return 1;
320
+ }
321
+
322
+ static void
323
+ pkey_blocking_gen_stop(void *ptr)
324
+ {
325
+ struct pkey_blocking_generate_arg *arg = ptr;
326
+ arg->interrupted = 1;
327
+ }
328
+
329
+ static void *
330
+ pkey_blocking_gen(void *ptr)
331
+ {
332
+ struct pkey_blocking_generate_arg *arg = ptr;
333
+
334
+ if (arg->genparam && EVP_PKEY_paramgen(arg->ctx, &arg->pkey) <= 0)
335
+ return NULL;
336
+ if (!arg->genparam && EVP_PKEY_keygen(arg->ctx, &arg->pkey) <= 0)
337
+ return NULL;
338
+ return arg->pkey;
339
+ }
340
+
341
+ static VALUE
342
+ pkey_generate(int argc, VALUE *argv, VALUE self, int genparam)
343
+ {
344
+ EVP_PKEY_CTX *ctx;
345
+ VALUE alg, options;
346
+ struct pkey_blocking_generate_arg gen_arg = { 0 };
347
+ int state;
348
+
349
+ rb_scan_args(argc, argv, "11", &alg, &options);
350
+ if (rb_obj_is_kind_of(alg, cPKey)) {
351
+ EVP_PKEY *base_pkey;
352
+
353
+ GetPKey(alg, base_pkey);
354
+ ctx = EVP_PKEY_CTX_new(base_pkey, NULL/* engine */);
355
+ if (!ctx)
356
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
357
+ }
358
+ else {
359
+ #if OSSL_OPENSSL_PREREQ(3, 0, 0)
360
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, StringValueCStr(alg), NULL);
361
+ if (!ctx)
362
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_from_name");
363
+ #else
364
+ const EVP_PKEY_ASN1_METHOD *ameth;
365
+ ENGINE *tmpeng;
366
+ int pkey_id;
367
+
368
+ StringValue(alg);
369
+ ameth = EVP_PKEY_asn1_find_str(&tmpeng, RSTRING_PTR(alg),
370
+ RSTRING_LENINT(alg));
371
+ if (!ameth)
372
+ ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", alg);
373
+ EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
374
+ #if !defined(OPENSSL_NO_ENGINE)
375
+ if (tmpeng)
376
+ ENGINE_finish(tmpeng);
377
+ #endif
378
+
379
+ ctx = EVP_PKEY_CTX_new_id(pkey_id, NULL/* engine */);
380
+ if (!ctx)
381
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new_id");
382
+ #endif
383
+ }
384
+
385
+ if (genparam && EVP_PKEY_paramgen_init(ctx) <= 0) {
386
+ EVP_PKEY_CTX_free(ctx);
387
+ ossl_raise(ePKeyError, "EVP_PKEY_paramgen_init");
388
+ }
389
+ if (!genparam && EVP_PKEY_keygen_init(ctx) <= 0) {
390
+ EVP_PKEY_CTX_free(ctx);
391
+ ossl_raise(ePKeyError, "EVP_PKEY_keygen_init");
392
+ }
393
+
394
+ if (!NIL_P(options)) {
395
+ pkey_ctx_apply_options(ctx, options, &state);
396
+ if (state) {
397
+ EVP_PKEY_CTX_free(ctx);
398
+ rb_jump_tag(state);
399
+ }
400
+ }
401
+
402
+ gen_arg.genparam = genparam;
403
+ gen_arg.ctx = ctx;
404
+ gen_arg.yield = rb_block_given_p();
405
+ EVP_PKEY_CTX_set_app_data(ctx, &gen_arg);
406
+ EVP_PKEY_CTX_set_cb(ctx, pkey_gen_cb);
407
+ if (gen_arg.yield)
408
+ pkey_blocking_gen(&gen_arg);
409
+ else
410
+ rb_thread_call_without_gvl(pkey_blocking_gen, &gen_arg,
411
+ pkey_blocking_gen_stop, &gen_arg);
412
+ EVP_PKEY_CTX_free(ctx);
413
+ if (!gen_arg.pkey) {
414
+ if (gen_arg.state) {
415
+ ossl_clear_error();
416
+ rb_jump_tag(gen_arg.state);
417
+ }
418
+ else {
419
+ ossl_raise(ePKeyError, genparam ? "EVP_PKEY_paramgen" : "EVP_PKEY_keygen");
420
+ }
421
+ }
422
+
423
+ return ossl_pkey_new(gen_arg.pkey);
424
+ }
425
+
426
+ /*
427
+ * call-seq:
428
+ * OpenSSL::PKey.generate_parameters(algo_name [, options]) -> pkey
429
+ *
430
+ * Generates new parameters for the algorithm. _algo_name_ is a String that
431
+ * represents the algorithm. The optional argument _options_ is a Hash that
432
+ * specifies the options specific to the algorithm. The order of the options
433
+ * can be important.
434
+ *
435
+ * A block can be passed optionally. The meaning of the arguments passed to
436
+ * the block varies depending on the implementation of the algorithm. The block
437
+ * may be called once or multiple times, or may not even be called.
438
+ *
439
+ * For the supported options, see the documentation for the 'openssl genpkey'
440
+ * utility command.
441
+ *
442
+ * == Example
443
+ * pkey = OpenSSL::PKey.generate_parameters("DSA", "dsa_paramgen_bits" => 2048)
444
+ * p pkey.p.num_bits #=> 2048
445
+ */
446
+ static VALUE
447
+ ossl_pkey_s_generate_parameters(int argc, VALUE *argv, VALUE self)
448
+ {
449
+ return pkey_generate(argc, argv, self, 1);
450
+ }
451
+
452
+ /*
453
+ * call-seq:
454
+ * OpenSSL::PKey.generate_key(algo_name [, options]) -> pkey
455
+ * OpenSSL::PKey.generate_key(pkey [, options]) -> pkey
456
+ *
457
+ * Generates a new key (pair).
458
+ *
459
+ * If a String is given as the first argument, it generates a new random key
460
+ * for the algorithm specified by the name just as ::generate_parameters does.
461
+ * If an OpenSSL::PKey::PKey is given instead, it generates a new random key
462
+ * for the same algorithm as the key, using the parameters the key contains.
463
+ *
464
+ * See ::generate_parameters for the details of _options_ and the given block.
465
+ *
466
+ * == Example
467
+ * pkey_params = OpenSSL::PKey.generate_parameters("DSA", "dsa_paramgen_bits" => 2048)
468
+ * pkey_params.priv_key #=> nil
469
+ * pkey = OpenSSL::PKey.generate_key(pkey_params)
470
+ * pkey.priv_key #=> #<OpenSSL::BN 6277...
471
+ */
472
+ static VALUE
473
+ ossl_pkey_s_generate_key(int argc, VALUE *argv, VALUE self)
474
+ {
475
+ return pkey_generate(argc, argv, self, 0);
476
+ }
477
+
478
+ /*
479
+ * TODO: There is no convenient way to check the presence of public key
480
+ * components on OpenSSL 3.0. But since keys are immutable on 3.0, pkeys without
481
+ * these should only be created by OpenSSL::PKey.generate_parameters or by
482
+ * parsing DER-/PEM-encoded string. We would need another flag for that.
483
+ */
188
484
  void
189
485
  ossl_pkey_check_public_key(const EVP_PKEY *pkey)
190
486
  {
487
+ #if OSSL_OPENSSL_PREREQ(3, 0, 0)
488
+ if (EVP_PKEY_missing_parameters(pkey))
489
+ ossl_raise(ePKeyError, "parameters missing");
490
+ #else
191
491
  void *ptr;
192
492
  const BIGNUM *n, *e, *pubkey;
193
493
 
@@ -223,6 +523,7 @@ ossl_pkey_check_public_key(const EVP_PKEY *pkey)
223
523
  return;
224
524
  }
225
525
  ossl_raise(ePKeyError, "public key missing");
526
+ #endif
226
527
  }
227
528
 
228
529
  EVP_PKEY *
@@ -240,12 +541,19 @@ GetPrivPKeyPtr(VALUE obj)
240
541
  {
241
542
  EVP_PKEY *pkey;
242
543
 
243
- if (rb_funcallv(obj, id_private_q, 0, NULL) != Qtrue) {
244
- ossl_raise(rb_eArgError, "Private key is needed.");
245
- }
246
544
  GetPKey(obj, pkey);
545
+ if (OSSL_PKEY_IS_PRIVATE(obj))
546
+ return pkey;
547
+ /*
548
+ * The EVP API does not provide a way to check if the EVP_PKEY has private
549
+ * components. Assuming it does...
550
+ */
551
+ if (!rb_respond_to(obj, id_private_q))
552
+ return pkey;
553
+ if (RTEST(rb_funcallv(obj, id_private_q, 0, NULL)))
554
+ return pkey;
247
555
 
248
- return pkey;
556
+ rb_raise(rb_eArgError, "private key is needed");
249
557
  }
250
558
 
251
559
  EVP_PKEY *
@@ -265,16 +573,7 @@ DupPKeyPtr(VALUE obj)
265
573
  static VALUE
266
574
  ossl_pkey_alloc(VALUE klass)
267
575
  {
268
- EVP_PKEY *pkey;
269
- VALUE obj;
270
-
271
- obj = NewPKey(klass);
272
- if (!(pkey = EVP_PKEY_new())) {
273
- ossl_raise(ePKeyError, NULL);
274
- }
275
- SetPKey(obj, pkey);
276
-
277
- return obj;
576
+ return TypedData_Wrap_Struct(klass, &ossl_evp_pkey_type, NULL);
278
577
  }
279
578
 
280
579
  /*
@@ -293,118 +592,915 @@ ossl_pkey_initialize(VALUE self)
293
592
  return self;
294
593
  }
295
594
 
595
+ #ifdef HAVE_EVP_PKEY_DUP
596
+ static VALUE
597
+ ossl_pkey_initialize_copy(VALUE self, VALUE other)
598
+ {
599
+ EVP_PKEY *pkey, *pkey_other;
600
+
601
+ TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey);
602
+ TypedData_Get_Struct(other, EVP_PKEY, &ossl_evp_pkey_type, pkey_other);
603
+ if (pkey)
604
+ rb_raise(rb_eTypeError, "pkey already initialized");
605
+ if (pkey_other) {
606
+ pkey = EVP_PKEY_dup(pkey_other);
607
+ if (!pkey)
608
+ ossl_raise(ePKeyError, "EVP_PKEY_dup");
609
+ RTYPEDDATA_DATA(self) = pkey;
610
+ }
611
+ return self;
612
+ }
613
+ #endif
614
+
615
+ /*
616
+ * call-seq:
617
+ * pkey.oid -> string
618
+ *
619
+ * Returns the short name of the OID associated with _pkey_.
620
+ */
621
+ static VALUE
622
+ ossl_pkey_oid(VALUE self)
623
+ {
624
+ EVP_PKEY *pkey;
625
+ int nid;
626
+
627
+ GetPKey(self, pkey);
628
+ nid = EVP_PKEY_id(pkey);
629
+ return rb_str_new_cstr(OBJ_nid2sn(nid));
630
+ }
631
+
632
+ /*
633
+ * call-seq:
634
+ * pkey.inspect -> string
635
+ *
636
+ * Returns a string describing the PKey object.
637
+ */
638
+ static VALUE
639
+ ossl_pkey_inspect(VALUE self)
640
+ {
641
+ EVP_PKEY *pkey;
642
+ int nid;
643
+
644
+ GetPKey(self, pkey);
645
+ nid = EVP_PKEY_id(pkey);
646
+ return rb_sprintf("#<%"PRIsVALUE":%p oid=%s>",
647
+ rb_class_name(CLASS_OF(self)), (void *)self,
648
+ OBJ_nid2sn(nid));
649
+ }
650
+
651
+ /*
652
+ * call-seq:
653
+ * pkey.to_text -> string
654
+ *
655
+ * Dumps key parameters, public key, and private key components contained in
656
+ * the key into a human-readable text.
657
+ *
658
+ * This is intended for debugging purpose.
659
+ *
660
+ * See also the man page EVP_PKEY_print_private(3).
661
+ */
662
+ static VALUE
663
+ ossl_pkey_to_text(VALUE self)
664
+ {
665
+ EVP_PKEY *pkey;
666
+ BIO *bio;
667
+
668
+ GetPKey(self, pkey);
669
+ if (!(bio = BIO_new(BIO_s_mem())))
670
+ ossl_raise(ePKeyError, "BIO_new");
671
+
672
+ if (EVP_PKEY_print_private(bio, pkey, 0, NULL) == 1)
673
+ goto out;
674
+ OSSL_BIO_reset(bio);
675
+ if (EVP_PKEY_print_public(bio, pkey, 0, NULL) == 1)
676
+ goto out;
677
+ OSSL_BIO_reset(bio);
678
+ if (EVP_PKEY_print_params(bio, pkey, 0, NULL) == 1)
679
+ goto out;
680
+
681
+ BIO_free(bio);
682
+ ossl_raise(ePKeyError, "EVP_PKEY_print_params");
683
+
684
+ out:
685
+ return ossl_membio2str(bio);
686
+ }
687
+
688
+ VALUE
689
+ ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, int to_der)
690
+ {
691
+ EVP_PKEY *pkey;
692
+ VALUE cipher, pass;
693
+ const EVP_CIPHER *enc = NULL;
694
+ BIO *bio;
695
+
696
+ GetPKey(self, pkey);
697
+ rb_scan_args(argc, argv, "02", &cipher, &pass);
698
+ if (!NIL_P(cipher)) {
699
+ enc = ossl_evp_get_cipherbyname(cipher);
700
+ pass = ossl_pem_passwd_value(pass);
701
+ }
702
+
703
+ bio = BIO_new(BIO_s_mem());
704
+ if (!bio)
705
+ ossl_raise(ePKeyError, "BIO_new");
706
+ if (to_der) {
707
+ if (!i2d_PrivateKey_bio(bio, pkey)) {
708
+ BIO_free(bio);
709
+ ossl_raise(ePKeyError, "i2d_PrivateKey_bio");
710
+ }
711
+ }
712
+ else {
713
+ #if OSSL_OPENSSL_PREREQ(1, 1, 0) || OSSL_LIBRESSL_PREREQ(3, 5, 0)
714
+ if (!PEM_write_bio_PrivateKey_traditional(bio, pkey, enc, NULL, 0,
715
+ ossl_pem_passwd_cb,
716
+ (void *)pass)) {
717
+ #else
718
+ char pem_str[80];
719
+ const char *aname;
720
+
721
+ EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &aname, pkey->ameth);
722
+ snprintf(pem_str, sizeof(pem_str), "%s PRIVATE KEY", aname);
723
+ if (!PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey, pem_str, bio,
724
+ pkey, enc, NULL, 0, ossl_pem_passwd_cb,
725
+ (void *)pass)) {
726
+ #endif
727
+ BIO_free(bio);
728
+ ossl_raise(ePKeyError, "PEM_write_bio_PrivateKey_traditional");
729
+ }
730
+ }
731
+ return ossl_membio2str(bio);
732
+ }
733
+
734
+ static VALUE
735
+ do_pkcs8_export(int argc, VALUE *argv, VALUE self, int to_der)
736
+ {
737
+ EVP_PKEY *pkey;
738
+ VALUE cipher, pass;
739
+ const EVP_CIPHER *enc = NULL;
740
+ BIO *bio;
741
+
742
+ GetPKey(self, pkey);
743
+ rb_scan_args(argc, argv, "02", &cipher, &pass);
744
+ if (argc > 0) {
745
+ /*
746
+ * TODO: EncryptedPrivateKeyInfo actually has more options.
747
+ * Should they be exposed?
748
+ */
749
+ enc = ossl_evp_get_cipherbyname(cipher);
750
+ pass = ossl_pem_passwd_value(pass);
751
+ }
752
+
753
+ bio = BIO_new(BIO_s_mem());
754
+ if (!bio)
755
+ ossl_raise(ePKeyError, "BIO_new");
756
+ if (to_der) {
757
+ if (!i2d_PKCS8PrivateKey_bio(bio, pkey, enc, NULL, 0,
758
+ ossl_pem_passwd_cb, (void *)pass)) {
759
+ BIO_free(bio);
760
+ ossl_raise(ePKeyError, "i2d_PKCS8PrivateKey_bio");
761
+ }
762
+ }
763
+ else {
764
+ if (!PEM_write_bio_PKCS8PrivateKey(bio, pkey, enc, NULL, 0,
765
+ ossl_pem_passwd_cb, (void *)pass)) {
766
+ BIO_free(bio);
767
+ ossl_raise(ePKeyError, "PEM_write_bio_PKCS8PrivateKey");
768
+ }
769
+ }
770
+ return ossl_membio2str(bio);
771
+ }
772
+
773
+ /*
774
+ * call-seq:
775
+ * pkey.private_to_der -> string
776
+ * pkey.private_to_der(cipher, password) -> string
777
+ *
778
+ * Serializes the private key to DER-encoded PKCS #8 format. If called without
779
+ * arguments, unencrypted PKCS #8 PrivateKeyInfo format is used. If called with
780
+ * a cipher name and a password, PKCS #8 EncryptedPrivateKeyInfo format with
781
+ * PBES2 encryption scheme is used.
782
+ */
783
+ static VALUE
784
+ ossl_pkey_private_to_der(int argc, VALUE *argv, VALUE self)
785
+ {
786
+ return do_pkcs8_export(argc, argv, self, 1);
787
+ }
788
+
789
+ /*
790
+ * call-seq:
791
+ * pkey.private_to_pem -> string
792
+ * pkey.private_to_pem(cipher, password) -> string
793
+ *
794
+ * Serializes the private key to PEM-encoded PKCS #8 format. See #private_to_der
795
+ * for more details.
796
+ */
797
+ static VALUE
798
+ ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self)
799
+ {
800
+ return do_pkcs8_export(argc, argv, self, 0);
801
+ }
802
+
803
+ VALUE
804
+ ossl_pkey_export_spki(VALUE self, int to_der)
805
+ {
806
+ EVP_PKEY *pkey;
807
+ BIO *bio;
808
+
809
+ GetPKey(self, pkey);
810
+ bio = BIO_new(BIO_s_mem());
811
+ if (!bio)
812
+ ossl_raise(ePKeyError, "BIO_new");
813
+ if (to_der) {
814
+ if (!i2d_PUBKEY_bio(bio, pkey)) {
815
+ BIO_free(bio);
816
+ ossl_raise(ePKeyError, "i2d_PUBKEY_bio");
817
+ }
818
+ }
819
+ else {
820
+ if (!PEM_write_bio_PUBKEY(bio, pkey)) {
821
+ BIO_free(bio);
822
+ ossl_raise(ePKeyError, "PEM_write_bio_PUBKEY");
823
+ }
824
+ }
825
+ return ossl_membio2str(bio);
826
+ }
827
+
828
+ /*
829
+ * call-seq:
830
+ * pkey.public_to_der -> string
831
+ *
832
+ * Serializes the public key to DER-encoded X.509 SubjectPublicKeyInfo format.
833
+ */
834
+ static VALUE
835
+ ossl_pkey_public_to_der(VALUE self)
836
+ {
837
+ return ossl_pkey_export_spki(self, 1);
838
+ }
839
+
840
+ /*
841
+ * call-seq:
842
+ * pkey.public_to_pem -> string
843
+ *
844
+ * Serializes the public key to PEM-encoded X.509 SubjectPublicKeyInfo format.
845
+ */
846
+ static VALUE
847
+ ossl_pkey_public_to_pem(VALUE self)
848
+ {
849
+ return ossl_pkey_export_spki(self, 0);
850
+ }
851
+
296
852
  /*
297
853
  * call-seq:
298
- * pkey.sign(digest, data) -> String
854
+ * pkey.compare?(another_pkey) -> true | false
299
855
  *
300
- * To sign the String _data_, _digest_, an instance of OpenSSL::Digest, must
301
- * be provided. The return value is again a String containing the signature.
302
- * A PKeyError is raised should errors occur.
303
- * Any previous state of the Digest instance is irrelevant to the signature
304
- * outcome, the digest instance is reset to its initial state during the
305
- * operation.
856
+ * Used primarily to check if an OpenSSL::X509::Certificate#public_key compares to its private key.
306
857
  *
307
858
  * == Example
308
- * data = 'Sign me!'
309
- * digest = OpenSSL::Digest::SHA256.new
310
- * pkey = OpenSSL::PKey::RSA.new(2048)
311
- * signature = pkey.sign(digest, data)
859
+ * x509 = OpenSSL::X509::Certificate.new(pem_encoded_certificate)
860
+ * rsa_key = OpenSSL::PKey::RSA.new(pem_encoded_private_key)
861
+ *
862
+ * rsa_key.compare?(x509.public_key) => true | false
312
863
  */
313
864
  static VALUE
314
- ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
865
+ ossl_pkey_compare(VALUE self, VALUE other)
866
+ {
867
+ int ret;
868
+ EVP_PKEY *selfPKey;
869
+ EVP_PKEY *otherPKey;
870
+
871
+ GetPKey(self, selfPKey);
872
+ GetPKey(other, otherPKey);
873
+
874
+ /* Explicitly check the key type given EVP_PKEY_ASN1_METHOD(3)
875
+ * docs param_cmp could return any negative number.
876
+ */
877
+ if (EVP_PKEY_id(selfPKey) != EVP_PKEY_id(otherPKey))
878
+ ossl_raise(rb_eTypeError, "cannot match different PKey types");
879
+
880
+ ret = EVP_PKEY_eq(selfPKey, otherPKey);
881
+
882
+ if (ret == 0)
883
+ return Qfalse;
884
+ else if (ret == 1)
885
+ return Qtrue;
886
+ else
887
+ ossl_raise(ePKeyError, "EVP_PKEY_eq");
888
+ }
889
+
890
+ /*
891
+ * call-seq:
892
+ * pkey.sign(digest, data [, options]) -> string
893
+ *
894
+ * Hashes and signs the +data+ using a message digest algorithm +digest+ and
895
+ * a private key +pkey+.
896
+ *
897
+ * See #verify for the verification operation.
898
+ *
899
+ * See also the man page EVP_DigestSign(3).
900
+ *
901
+ * +digest+::
902
+ * A String that represents the message digest algorithm name, or +nil+
903
+ * if the PKey type requires no digest algorithm.
904
+ * For backwards compatibility, this can be an instance of OpenSSL::Digest.
905
+ * Its state will not affect the signature.
906
+ * +data+::
907
+ * A String. The data to be hashed and signed.
908
+ * +options+::
909
+ * A Hash that contains algorithm specific control operations to \OpenSSL.
910
+ * See OpenSSL's man page EVP_PKEY_CTX_ctrl_str(3) for details.
911
+ * +options+ parameter was added in version 3.0.
912
+ *
913
+ * Example:
914
+ * data = "Sign me!"
915
+ * pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048)
916
+ * signopts = { rsa_padding_mode: "pss" }
917
+ * signature = pkey.sign("SHA256", data, signopts)
918
+ *
919
+ * # Creates a copy of the RSA key pkey, but without the private components
920
+ * pub_key = pkey.public_key
921
+ * puts pub_key.verify("SHA256", signature, data, signopts) # => true
922
+ */
923
+ static VALUE
924
+ ossl_pkey_sign(int argc, VALUE *argv, VALUE self)
315
925
  {
316
926
  EVP_PKEY *pkey;
317
- const EVP_MD *md;
927
+ VALUE digest, data, options, sig;
928
+ const EVP_MD *md = NULL;
318
929
  EVP_MD_CTX *ctx;
319
- unsigned int buf_len;
320
- VALUE str;
321
- int result;
930
+ EVP_PKEY_CTX *pctx;
931
+ size_t siglen;
932
+ int state;
322
933
 
323
934
  pkey = GetPrivPKeyPtr(self);
324
- md = ossl_evp_get_digestbyname(digest);
935
+ rb_scan_args(argc, argv, "21", &digest, &data, &options);
936
+ if (!NIL_P(digest))
937
+ md = ossl_evp_get_digestbyname(digest);
325
938
  StringValue(data);
326
- str = rb_str_new(0, EVP_PKEY_size(pkey));
327
939
 
328
940
  ctx = EVP_MD_CTX_new();
329
941
  if (!ctx)
330
- ossl_raise(ePKeyError, "EVP_MD_CTX_new");
331
- if (!EVP_SignInit_ex(ctx, md, NULL)) {
332
- EVP_MD_CTX_free(ctx);
333
- ossl_raise(ePKeyError, "EVP_SignInit_ex");
942
+ ossl_raise(ePKeyError, "EVP_MD_CTX_new");
943
+ if (EVP_DigestSignInit(ctx, &pctx, md, /* engine */NULL, pkey) < 1) {
944
+ EVP_MD_CTX_free(ctx);
945
+ ossl_raise(ePKeyError, "EVP_DigestSignInit");
946
+ }
947
+ if (!NIL_P(options)) {
948
+ pkey_ctx_apply_options(pctx, options, &state);
949
+ if (state) {
950
+ EVP_MD_CTX_free(ctx);
951
+ rb_jump_tag(state);
952
+ }
953
+ }
954
+ #if OSSL_OPENSSL_PREREQ(1, 1, 1) || OSSL_LIBRESSL_PREREQ(3, 4, 0)
955
+ if (EVP_DigestSign(ctx, NULL, &siglen, (unsigned char *)RSTRING_PTR(data),
956
+ RSTRING_LEN(data)) < 1) {
957
+ EVP_MD_CTX_free(ctx);
958
+ ossl_raise(ePKeyError, "EVP_DigestSign");
959
+ }
960
+ if (siglen > LONG_MAX) {
961
+ EVP_MD_CTX_free(ctx);
962
+ rb_raise(ePKeyError, "signature would be too large");
334
963
  }
335
- if (!EVP_SignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data))) {
336
- EVP_MD_CTX_free(ctx);
337
- ossl_raise(ePKeyError, "EVP_SignUpdate");
964
+ sig = ossl_str_new(NULL, (long)siglen, &state);
965
+ if (state) {
966
+ EVP_MD_CTX_free(ctx);
967
+ rb_jump_tag(state);
338
968
  }
339
- result = EVP_SignFinal(ctx, (unsigned char *)RSTRING_PTR(str), &buf_len, pkey);
969
+ if (EVP_DigestSign(ctx, (unsigned char *)RSTRING_PTR(sig), &siglen,
970
+ (unsigned char *)RSTRING_PTR(data),
971
+ RSTRING_LEN(data)) < 1) {
972
+ EVP_MD_CTX_free(ctx);
973
+ ossl_raise(ePKeyError, "EVP_DigestSign");
974
+ }
975
+ #else
976
+ if (EVP_DigestSignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) < 1) {
977
+ EVP_MD_CTX_free(ctx);
978
+ ossl_raise(ePKeyError, "EVP_DigestSignUpdate");
979
+ }
980
+ if (EVP_DigestSignFinal(ctx, NULL, &siglen) < 1) {
981
+ EVP_MD_CTX_free(ctx);
982
+ ossl_raise(ePKeyError, "EVP_DigestSignFinal");
983
+ }
984
+ if (siglen > LONG_MAX) {
985
+ EVP_MD_CTX_free(ctx);
986
+ rb_raise(ePKeyError, "signature would be too large");
987
+ }
988
+ sig = ossl_str_new(NULL, (long)siglen, &state);
989
+ if (state) {
990
+ EVP_MD_CTX_free(ctx);
991
+ rb_jump_tag(state);
992
+ }
993
+ if (EVP_DigestSignFinal(ctx, (unsigned char *)RSTRING_PTR(sig),
994
+ &siglen) < 1) {
995
+ EVP_MD_CTX_free(ctx);
996
+ ossl_raise(ePKeyError, "EVP_DigestSignFinal");
997
+ }
998
+ #endif
340
999
  EVP_MD_CTX_free(ctx);
341
- if (!result)
342
- ossl_raise(ePKeyError, "EVP_SignFinal");
343
- rb_str_set_len(str, buf_len);
344
-
345
- return str;
1000
+ rb_str_set_len(sig, siglen);
1001
+ return sig;
346
1002
  }
347
1003
 
348
1004
  /*
349
- * call-seq:
350
- * pkey.verify(digest, signature, data) -> String
1005
+ * call-seq:
1006
+ * pkey.verify(digest, signature, data [, options]) -> true or false
351
1007
  *
352
- * To verify the String _signature_, _digest_, an instance of
353
- * OpenSSL::Digest, must be provided to re-compute the message digest of the
354
- * original _data_, also a String. The return value is +true+ if the
355
- * signature is valid, +false+ otherwise. A PKeyError is raised should errors
356
- * occur.
357
- * Any previous state of the Digest instance is irrelevant to the validation
358
- * outcome, the digest instance is reset to its initial state during the
359
- * operation.
1008
+ * Verifies the +signature+ for the +data+ using a message digest algorithm
1009
+ * +digest+ and a public key +pkey+.
360
1010
  *
361
- * == Example
362
- * data = 'Sign me!'
363
- * digest = OpenSSL::Digest::SHA256.new
364
- * pkey = OpenSSL::PKey::RSA.new(2048)
365
- * signature = pkey.sign(digest, data)
366
- * pub_key = pkey.public_key
367
- * puts pub_key.verify(digest, signature, data) # => true
1011
+ * Returns +true+ if the signature is successfully verified, +false+ otherwise.
1012
+ * The caller must check the return value.
1013
+ *
1014
+ * See #sign for the signing operation and an example.
1015
+ *
1016
+ * See also the man page EVP_DigestVerify(3).
1017
+ *
1018
+ * +digest+::
1019
+ * See #sign.
1020
+ * +signature+::
1021
+ * A String containing the signature to be verified.
1022
+ * +data+::
1023
+ * See #sign.
1024
+ * +options+::
1025
+ * See #sign. +options+ parameter was added in version 3.0.
368
1026
  */
369
1027
  static VALUE
370
- ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
1028
+ ossl_pkey_verify(int argc, VALUE *argv, VALUE self)
371
1029
  {
372
1030
  EVP_PKEY *pkey;
373
- const EVP_MD *md;
1031
+ VALUE digest, sig, data, options;
1032
+ const EVP_MD *md = NULL;
374
1033
  EVP_MD_CTX *ctx;
375
- int siglen, result;
1034
+ EVP_PKEY_CTX *pctx;
1035
+ int state, ret;
376
1036
 
377
1037
  GetPKey(self, pkey);
1038
+ rb_scan_args(argc, argv, "31", &digest, &sig, &data, &options);
378
1039
  ossl_pkey_check_public_key(pkey);
379
- md = ossl_evp_get_digestbyname(digest);
1040
+ if (!NIL_P(digest))
1041
+ md = ossl_evp_get_digestbyname(digest);
380
1042
  StringValue(sig);
381
- siglen = RSTRING_LENINT(sig);
382
1043
  StringValue(data);
383
1044
 
384
1045
  ctx = EVP_MD_CTX_new();
385
1046
  if (!ctx)
386
- ossl_raise(ePKeyError, "EVP_MD_CTX_new");
387
- if (!EVP_VerifyInit_ex(ctx, md, NULL)) {
388
- EVP_MD_CTX_free(ctx);
389
- ossl_raise(ePKeyError, "EVP_VerifyInit_ex");
1047
+ ossl_raise(ePKeyError, "EVP_MD_CTX_new");
1048
+ if (EVP_DigestVerifyInit(ctx, &pctx, md, /* engine */NULL, pkey) < 1) {
1049
+ EVP_MD_CTX_free(ctx);
1050
+ ossl_raise(ePKeyError, "EVP_DigestVerifyInit");
390
1051
  }
391
- if (!EVP_VerifyUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data))) {
392
- EVP_MD_CTX_free(ctx);
393
- ossl_raise(ePKeyError, "EVP_VerifyUpdate");
1052
+ if (!NIL_P(options)) {
1053
+ pkey_ctx_apply_options(pctx, options, &state);
1054
+ if (state) {
1055
+ EVP_MD_CTX_free(ctx);
1056
+ rb_jump_tag(state);
1057
+ }
394
1058
  }
395
- result = EVP_VerifyFinal(ctx, (unsigned char *)RSTRING_PTR(sig), siglen, pkey);
1059
+ #if OSSL_OPENSSL_PREREQ(1, 1, 1) || OSSL_LIBRESSL_PREREQ(3, 4, 0)
1060
+ ret = EVP_DigestVerify(ctx, (unsigned char *)RSTRING_PTR(sig),
1061
+ RSTRING_LEN(sig), (unsigned char *)RSTRING_PTR(data),
1062
+ RSTRING_LEN(data));
396
1063
  EVP_MD_CTX_free(ctx);
397
- switch (result) {
398
- case 0:
399
- ossl_clear_error();
400
- return Qfalse;
401
- case 1:
402
- return Qtrue;
403
- default:
404
- ossl_raise(ePKeyError, "EVP_VerifyFinal");
1064
+ if (ret < 0)
1065
+ ossl_raise(ePKeyError, "EVP_DigestVerify");
1066
+ #else
1067
+ if (EVP_DigestVerifyUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) < 1) {
1068
+ EVP_MD_CTX_free(ctx);
1069
+ ossl_raise(ePKeyError, "EVP_DigestVerifyUpdate");
1070
+ }
1071
+ ret = EVP_DigestVerifyFinal(ctx, (unsigned char *)RSTRING_PTR(sig),
1072
+ RSTRING_LEN(sig));
1073
+ EVP_MD_CTX_free(ctx);
1074
+ if (ret < 0)
1075
+ ossl_raise(ePKeyError, "EVP_DigestVerifyFinal");
1076
+ #endif
1077
+ if (ret)
1078
+ return Qtrue;
1079
+ else {
1080
+ ossl_clear_error();
1081
+ return Qfalse;
405
1082
  }
406
1083
  }
407
1084
 
1085
+ /*
1086
+ * call-seq:
1087
+ * pkey.sign_raw(digest, data [, options]) -> string
1088
+ *
1089
+ * Signs +data+ using a private key +pkey+. Unlike #sign, +data+ will not be
1090
+ * hashed by +digest+ automatically.
1091
+ *
1092
+ * See #verify_raw for the verification operation.
1093
+ *
1094
+ * Added in version 3.0. See also the man page EVP_PKEY_sign(3).
1095
+ *
1096
+ * +digest+::
1097
+ * A String that represents the message digest algorithm name, or +nil+
1098
+ * if the PKey type requires no digest algorithm.
1099
+ * Although this method will not hash +data+ with it, this parameter may still
1100
+ * be required depending on the signature algorithm.
1101
+ * +data+::
1102
+ * A String. The data to be signed.
1103
+ * +options+::
1104
+ * A Hash that contains algorithm specific control operations to \OpenSSL.
1105
+ * See OpenSSL's man page EVP_PKEY_CTX_ctrl_str(3) for details.
1106
+ *
1107
+ * Example:
1108
+ * data = "Sign me!"
1109
+ * hash = OpenSSL::Digest.digest("SHA256", data)
1110
+ * pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048)
1111
+ * signopts = { rsa_padding_mode: "pss" }
1112
+ * signature = pkey.sign_raw("SHA256", hash, signopts)
1113
+ *
1114
+ * # Creates a copy of the RSA key pkey, but without the private components
1115
+ * pub_key = pkey.public_key
1116
+ * puts pub_key.verify_raw("SHA256", signature, hash, signopts) # => true
1117
+ */
1118
+ static VALUE
1119
+ ossl_pkey_sign_raw(int argc, VALUE *argv, VALUE self)
1120
+ {
1121
+ EVP_PKEY *pkey;
1122
+ VALUE digest, data, options, sig;
1123
+ const EVP_MD *md = NULL;
1124
+ EVP_PKEY_CTX *ctx;
1125
+ size_t outlen;
1126
+ int state;
1127
+
1128
+ GetPKey(self, pkey);
1129
+ rb_scan_args(argc, argv, "21", &digest, &data, &options);
1130
+ if (!NIL_P(digest))
1131
+ md = ossl_evp_get_digestbyname(digest);
1132
+ StringValue(data);
1133
+
1134
+ ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
1135
+ if (!ctx)
1136
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
1137
+ if (EVP_PKEY_sign_init(ctx) <= 0) {
1138
+ EVP_PKEY_CTX_free(ctx);
1139
+ ossl_raise(ePKeyError, "EVP_PKEY_sign_init");
1140
+ }
1141
+ if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) {
1142
+ EVP_PKEY_CTX_free(ctx);
1143
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md");
1144
+ }
1145
+ if (!NIL_P(options)) {
1146
+ pkey_ctx_apply_options(ctx, options, &state);
1147
+ if (state) {
1148
+ EVP_PKEY_CTX_free(ctx);
1149
+ rb_jump_tag(state);
1150
+ }
1151
+ }
1152
+ if (EVP_PKEY_sign(ctx, NULL, &outlen, (unsigned char *)RSTRING_PTR(data),
1153
+ RSTRING_LEN(data)) <= 0) {
1154
+ EVP_PKEY_CTX_free(ctx);
1155
+ ossl_raise(ePKeyError, "EVP_PKEY_sign");
1156
+ }
1157
+ if (outlen > LONG_MAX) {
1158
+ EVP_PKEY_CTX_free(ctx);
1159
+ rb_raise(ePKeyError, "signature would be too large");
1160
+ }
1161
+ sig = ossl_str_new(NULL, (long)outlen, &state);
1162
+ if (state) {
1163
+ EVP_PKEY_CTX_free(ctx);
1164
+ rb_jump_tag(state);
1165
+ }
1166
+ if (EVP_PKEY_sign(ctx, (unsigned char *)RSTRING_PTR(sig), &outlen,
1167
+ (unsigned char *)RSTRING_PTR(data),
1168
+ RSTRING_LEN(data)) <= 0) {
1169
+ EVP_PKEY_CTX_free(ctx);
1170
+ ossl_raise(ePKeyError, "EVP_PKEY_sign");
1171
+ }
1172
+ EVP_PKEY_CTX_free(ctx);
1173
+ rb_str_set_len(sig, outlen);
1174
+ return sig;
1175
+ }
1176
+
1177
+ /*
1178
+ * call-seq:
1179
+ * pkey.verify_raw(digest, signature, data [, options]) -> true or false
1180
+ *
1181
+ * Verifies the +signature+ for the +data+ using a public key +pkey+. Unlike
1182
+ * #verify, this method will not hash +data+ with +digest+ automatically.
1183
+ *
1184
+ * Returns +true+ if the signature is successfully verified, +false+ otherwise.
1185
+ * The caller must check the return value.
1186
+ *
1187
+ * See #sign_raw for the signing operation and an example code.
1188
+ *
1189
+ * Added in version 3.0. See also the man page EVP_PKEY_verify(3).
1190
+ *
1191
+ * +signature+::
1192
+ * A String containing the signature to be verified.
1193
+ */
1194
+ static VALUE
1195
+ ossl_pkey_verify_raw(int argc, VALUE *argv, VALUE self)
1196
+ {
1197
+ EVP_PKEY *pkey;
1198
+ VALUE digest, sig, data, options;
1199
+ const EVP_MD *md = NULL;
1200
+ EVP_PKEY_CTX *ctx;
1201
+ int state, ret;
1202
+
1203
+ GetPKey(self, pkey);
1204
+ rb_scan_args(argc, argv, "31", &digest, &sig, &data, &options);
1205
+ ossl_pkey_check_public_key(pkey);
1206
+ if (!NIL_P(digest))
1207
+ md = ossl_evp_get_digestbyname(digest);
1208
+ StringValue(sig);
1209
+ StringValue(data);
1210
+
1211
+ ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
1212
+ if (!ctx)
1213
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
1214
+ if (EVP_PKEY_verify_init(ctx) <= 0) {
1215
+ EVP_PKEY_CTX_free(ctx);
1216
+ ossl_raise(ePKeyError, "EVP_PKEY_verify_init");
1217
+ }
1218
+ if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) {
1219
+ EVP_PKEY_CTX_free(ctx);
1220
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md");
1221
+ }
1222
+ if (!NIL_P(options)) {
1223
+ pkey_ctx_apply_options(ctx, options, &state);
1224
+ if (state) {
1225
+ EVP_PKEY_CTX_free(ctx);
1226
+ rb_jump_tag(state);
1227
+ }
1228
+ }
1229
+ ret = EVP_PKEY_verify(ctx, (unsigned char *)RSTRING_PTR(sig),
1230
+ RSTRING_LEN(sig),
1231
+ (unsigned char *)RSTRING_PTR(data),
1232
+ RSTRING_LEN(data));
1233
+ EVP_PKEY_CTX_free(ctx);
1234
+ if (ret < 0)
1235
+ ossl_raise(ePKeyError, "EVP_PKEY_verify");
1236
+
1237
+ if (ret)
1238
+ return Qtrue;
1239
+ else {
1240
+ ossl_clear_error();
1241
+ return Qfalse;
1242
+ }
1243
+ }
1244
+
1245
+ /*
1246
+ * call-seq:
1247
+ * pkey.verify_recover(digest, signature [, options]) -> string
1248
+ *
1249
+ * Recovers the signed data from +signature+ using a public key +pkey+. Not all
1250
+ * signature algorithms support this operation.
1251
+ *
1252
+ * Added in version 3.0. See also the man page EVP_PKEY_verify_recover(3).
1253
+ *
1254
+ * +signature+::
1255
+ * A String containing the signature to be verified.
1256
+ */
1257
+ static VALUE
1258
+ ossl_pkey_verify_recover(int argc, VALUE *argv, VALUE self)
1259
+ {
1260
+ EVP_PKEY *pkey;
1261
+ VALUE digest, sig, options, out;
1262
+ const EVP_MD *md = NULL;
1263
+ EVP_PKEY_CTX *ctx;
1264
+ int state;
1265
+ size_t outlen;
1266
+
1267
+ GetPKey(self, pkey);
1268
+ rb_scan_args(argc, argv, "21", &digest, &sig, &options);
1269
+ ossl_pkey_check_public_key(pkey);
1270
+ if (!NIL_P(digest))
1271
+ md = ossl_evp_get_digestbyname(digest);
1272
+ StringValue(sig);
1273
+
1274
+ ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
1275
+ if (!ctx)
1276
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
1277
+ if (EVP_PKEY_verify_recover_init(ctx) <= 0) {
1278
+ EVP_PKEY_CTX_free(ctx);
1279
+ ossl_raise(ePKeyError, "EVP_PKEY_verify_recover_init");
1280
+ }
1281
+ if (md && EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) {
1282
+ EVP_PKEY_CTX_free(ctx);
1283
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_set_signature_md");
1284
+ }
1285
+ if (!NIL_P(options)) {
1286
+ pkey_ctx_apply_options(ctx, options, &state);
1287
+ if (state) {
1288
+ EVP_PKEY_CTX_free(ctx);
1289
+ rb_jump_tag(state);
1290
+ }
1291
+ }
1292
+ if (EVP_PKEY_verify_recover(ctx, NULL, &outlen,
1293
+ (unsigned char *)RSTRING_PTR(sig),
1294
+ RSTRING_LEN(sig)) <= 0) {
1295
+ EVP_PKEY_CTX_free(ctx);
1296
+ ossl_raise(ePKeyError, "EVP_PKEY_verify_recover");
1297
+ }
1298
+ out = ossl_str_new(NULL, (long)outlen, &state);
1299
+ if (state) {
1300
+ EVP_PKEY_CTX_free(ctx);
1301
+ rb_jump_tag(state);
1302
+ }
1303
+ if (EVP_PKEY_verify_recover(ctx, (unsigned char *)RSTRING_PTR(out), &outlen,
1304
+ (unsigned char *)RSTRING_PTR(sig),
1305
+ RSTRING_LEN(sig)) <= 0) {
1306
+ EVP_PKEY_CTX_free(ctx);
1307
+ ossl_raise(ePKeyError, "EVP_PKEY_verify_recover");
1308
+ }
1309
+ EVP_PKEY_CTX_free(ctx);
1310
+ rb_str_set_len(out, outlen);
1311
+ return out;
1312
+ }
1313
+
1314
+ /*
1315
+ * call-seq:
1316
+ * pkey.derive(peer_pkey) -> string
1317
+ *
1318
+ * Derives a shared secret from _pkey_ and _peer_pkey_. _pkey_ must contain
1319
+ * the private components, _peer_pkey_ must contain the public components.
1320
+ */
1321
+ static VALUE
1322
+ ossl_pkey_derive(int argc, VALUE *argv, VALUE self)
1323
+ {
1324
+ EVP_PKEY *pkey, *peer_pkey;
1325
+ EVP_PKEY_CTX *ctx;
1326
+ VALUE peer_pkey_obj, str;
1327
+ size_t keylen;
1328
+ int state;
1329
+
1330
+ GetPKey(self, pkey);
1331
+ rb_scan_args(argc, argv, "1", &peer_pkey_obj);
1332
+ GetPKey(peer_pkey_obj, peer_pkey);
1333
+
1334
+ ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
1335
+ if (!ctx)
1336
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
1337
+ if (EVP_PKEY_derive_init(ctx) <= 0) {
1338
+ EVP_PKEY_CTX_free(ctx);
1339
+ ossl_raise(ePKeyError, "EVP_PKEY_derive_init");
1340
+ }
1341
+ if (EVP_PKEY_derive_set_peer(ctx, peer_pkey) <= 0) {
1342
+ EVP_PKEY_CTX_free(ctx);
1343
+ ossl_raise(ePKeyError, "EVP_PKEY_derive_set_peer");
1344
+ }
1345
+ if (EVP_PKEY_derive(ctx, NULL, &keylen) <= 0) {
1346
+ EVP_PKEY_CTX_free(ctx);
1347
+ ossl_raise(ePKeyError, "EVP_PKEY_derive");
1348
+ }
1349
+ if (keylen > LONG_MAX)
1350
+ rb_raise(ePKeyError, "derived key would be too large");
1351
+ str = ossl_str_new(NULL, (long)keylen, &state);
1352
+ if (state) {
1353
+ EVP_PKEY_CTX_free(ctx);
1354
+ rb_jump_tag(state);
1355
+ }
1356
+ if (EVP_PKEY_derive(ctx, (unsigned char *)RSTRING_PTR(str), &keylen) <= 0) {
1357
+ EVP_PKEY_CTX_free(ctx);
1358
+ ossl_raise(ePKeyError, "EVP_PKEY_derive");
1359
+ }
1360
+ EVP_PKEY_CTX_free(ctx);
1361
+ rb_str_set_len(str, keylen);
1362
+ return str;
1363
+ }
1364
+
1365
+ /*
1366
+ * call-seq:
1367
+ * pkey.encrypt(data [, options]) -> string
1368
+ *
1369
+ * Performs a public key encryption operation using +pkey+.
1370
+ *
1371
+ * See #decrypt for the reverse operation.
1372
+ *
1373
+ * Added in version 3.0. See also the man page EVP_PKEY_encrypt(3).
1374
+ *
1375
+ * +data+::
1376
+ * A String to be encrypted.
1377
+ * +options+::
1378
+ * A Hash that contains algorithm specific control operations to \OpenSSL.
1379
+ * See OpenSSL's man page EVP_PKEY_CTX_ctrl_str(3) for details.
1380
+ *
1381
+ * Example:
1382
+ * pkey = OpenSSL::PKey.generate_key("RSA", rsa_keygen_bits: 2048)
1383
+ * data = "secret data"
1384
+ * encrypted = pkey.encrypt(data, rsa_padding_mode: "oaep")
1385
+ * decrypted = pkey.decrypt(data, rsa_padding_mode: "oaep")
1386
+ * p decrypted #=> "secret data"
1387
+ */
1388
+ static VALUE
1389
+ ossl_pkey_encrypt(int argc, VALUE *argv, VALUE self)
1390
+ {
1391
+ EVP_PKEY *pkey;
1392
+ EVP_PKEY_CTX *ctx;
1393
+ VALUE data, options, str;
1394
+ size_t outlen;
1395
+ int state;
1396
+
1397
+ GetPKey(self, pkey);
1398
+ rb_scan_args(argc, argv, "11", &data, &options);
1399
+ StringValue(data);
1400
+
1401
+ ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
1402
+ if (!ctx)
1403
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
1404
+ if (EVP_PKEY_encrypt_init(ctx) <= 0) {
1405
+ EVP_PKEY_CTX_free(ctx);
1406
+ ossl_raise(ePKeyError, "EVP_PKEY_encrypt_init");
1407
+ }
1408
+ if (!NIL_P(options)) {
1409
+ pkey_ctx_apply_options(ctx, options, &state);
1410
+ if (state) {
1411
+ EVP_PKEY_CTX_free(ctx);
1412
+ rb_jump_tag(state);
1413
+ }
1414
+ }
1415
+ if (EVP_PKEY_encrypt(ctx, NULL, &outlen,
1416
+ (unsigned char *)RSTRING_PTR(data),
1417
+ RSTRING_LEN(data)) <= 0) {
1418
+ EVP_PKEY_CTX_free(ctx);
1419
+ ossl_raise(ePKeyError, "EVP_PKEY_encrypt");
1420
+ }
1421
+ if (outlen > LONG_MAX) {
1422
+ EVP_PKEY_CTX_free(ctx);
1423
+ rb_raise(ePKeyError, "encrypted data would be too large");
1424
+ }
1425
+ str = ossl_str_new(NULL, (long)outlen, &state);
1426
+ if (state) {
1427
+ EVP_PKEY_CTX_free(ctx);
1428
+ rb_jump_tag(state);
1429
+ }
1430
+ if (EVP_PKEY_encrypt(ctx, (unsigned char *)RSTRING_PTR(str), &outlen,
1431
+ (unsigned char *)RSTRING_PTR(data),
1432
+ RSTRING_LEN(data)) <= 0) {
1433
+ EVP_PKEY_CTX_free(ctx);
1434
+ ossl_raise(ePKeyError, "EVP_PKEY_encrypt");
1435
+ }
1436
+ EVP_PKEY_CTX_free(ctx);
1437
+ rb_str_set_len(str, outlen);
1438
+ return str;
1439
+ }
1440
+
1441
+ /*
1442
+ * call-seq:
1443
+ * pkey.decrypt(data [, options]) -> string
1444
+ *
1445
+ * Performs a public key decryption operation using +pkey+.
1446
+ *
1447
+ * See #encrypt for a description of the parameters and an example.
1448
+ *
1449
+ * Added in version 3.0. See also the man page EVP_PKEY_decrypt(3).
1450
+ */
1451
+ static VALUE
1452
+ ossl_pkey_decrypt(int argc, VALUE *argv, VALUE self)
1453
+ {
1454
+ EVP_PKEY *pkey;
1455
+ EVP_PKEY_CTX *ctx;
1456
+ VALUE data, options, str;
1457
+ size_t outlen;
1458
+ int state;
1459
+
1460
+ GetPKey(self, pkey);
1461
+ rb_scan_args(argc, argv, "11", &data, &options);
1462
+ StringValue(data);
1463
+
1464
+ ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
1465
+ if (!ctx)
1466
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
1467
+ if (EVP_PKEY_decrypt_init(ctx) <= 0) {
1468
+ EVP_PKEY_CTX_free(ctx);
1469
+ ossl_raise(ePKeyError, "EVP_PKEY_decrypt_init");
1470
+ }
1471
+ if (!NIL_P(options)) {
1472
+ pkey_ctx_apply_options(ctx, options, &state);
1473
+ if (state) {
1474
+ EVP_PKEY_CTX_free(ctx);
1475
+ rb_jump_tag(state);
1476
+ }
1477
+ }
1478
+ if (EVP_PKEY_decrypt(ctx, NULL, &outlen,
1479
+ (unsigned char *)RSTRING_PTR(data),
1480
+ RSTRING_LEN(data)) <= 0) {
1481
+ EVP_PKEY_CTX_free(ctx);
1482
+ ossl_raise(ePKeyError, "EVP_PKEY_decrypt");
1483
+ }
1484
+ if (outlen > LONG_MAX) {
1485
+ EVP_PKEY_CTX_free(ctx);
1486
+ rb_raise(ePKeyError, "decrypted data would be too large");
1487
+ }
1488
+ str = ossl_str_new(NULL, (long)outlen, &state);
1489
+ if (state) {
1490
+ EVP_PKEY_CTX_free(ctx);
1491
+ rb_jump_tag(state);
1492
+ }
1493
+ if (EVP_PKEY_decrypt(ctx, (unsigned char *)RSTRING_PTR(str), &outlen,
1494
+ (unsigned char *)RSTRING_PTR(data),
1495
+ RSTRING_LEN(data)) <= 0) {
1496
+ EVP_PKEY_CTX_free(ctx);
1497
+ ossl_raise(ePKeyError, "EVP_PKEY_decrypt");
1498
+ }
1499
+ EVP_PKEY_CTX_free(ctx);
1500
+ rb_str_set_len(str, outlen);
1501
+ return str;
1502
+ }
1503
+
408
1504
  /*
409
1505
  * INIT
410
1506
  */
@@ -488,12 +1584,33 @@ Init_ossl_pkey(void)
488
1584
  cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
489
1585
 
490
1586
  rb_define_module_function(mPKey, "read", ossl_pkey_new_from_data, -1);
1587
+ rb_define_module_function(mPKey, "generate_parameters", ossl_pkey_s_generate_parameters, -1);
1588
+ rb_define_module_function(mPKey, "generate_key", ossl_pkey_s_generate_key, -1);
491
1589
 
492
1590
  rb_define_alloc_func(cPKey, ossl_pkey_alloc);
493
1591
  rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
1592
+ #ifdef HAVE_EVP_PKEY_DUP
1593
+ rb_define_method(cPKey, "initialize_copy", ossl_pkey_initialize_copy, 1);
1594
+ #else
1595
+ rb_undef_method(cPKey, "initialize_copy");
1596
+ #endif
1597
+ rb_define_method(cPKey, "oid", ossl_pkey_oid, 0);
1598
+ rb_define_method(cPKey, "inspect", ossl_pkey_inspect, 0);
1599
+ rb_define_method(cPKey, "to_text", ossl_pkey_to_text, 0);
1600
+ rb_define_method(cPKey, "private_to_der", ossl_pkey_private_to_der, -1);
1601
+ rb_define_method(cPKey, "private_to_pem", ossl_pkey_private_to_pem, -1);
1602
+ rb_define_method(cPKey, "public_to_der", ossl_pkey_public_to_der, 0);
1603
+ rb_define_method(cPKey, "public_to_pem", ossl_pkey_public_to_pem, 0);
1604
+ rb_define_method(cPKey, "compare?", ossl_pkey_compare, 1);
494
1605
 
495
- rb_define_method(cPKey, "sign", ossl_pkey_sign, 2);
496
- rb_define_method(cPKey, "verify", ossl_pkey_verify, 3);
1606
+ rb_define_method(cPKey, "sign", ossl_pkey_sign, -1);
1607
+ rb_define_method(cPKey, "verify", ossl_pkey_verify, -1);
1608
+ rb_define_method(cPKey, "sign_raw", ossl_pkey_sign_raw, -1);
1609
+ rb_define_method(cPKey, "verify_raw", ossl_pkey_verify_raw, -1);
1610
+ rb_define_method(cPKey, "verify_recover", ossl_pkey_verify_recover, -1);
1611
+ rb_define_method(cPKey, "derive", ossl_pkey_derive, -1);
1612
+ rb_define_method(cPKey, "encrypt", ossl_pkey_encrypt, -1);
1613
+ rb_define_method(cPKey, "decrypt", ossl_pkey_decrypt, -1);
497
1614
 
498
1615
  id_private_q = rb_intern("private?");
499
1616