openssl 2.1.2 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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