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