zig_example 0.3.2 → 0.3.4

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