openssl 2.1.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +35 -45
- data/History.md +232 -0
- data/README.md +2 -2
- data/ext/openssl/extconf.rb +61 -46
- data/ext/openssl/openssl_missing.c +0 -66
- data/ext/openssl/openssl_missing.h +60 -44
- data/ext/openssl/ossl.c +112 -66
- data/ext/openssl/ossl.h +28 -11
- data/ext/openssl/ossl_asn1.c +42 -5
- data/ext/openssl/ossl_bn.c +276 -146
- data/ext/openssl/ossl_bn.h +2 -1
- data/ext/openssl/ossl_cipher.c +38 -29
- data/ext/openssl/ossl_config.c +412 -41
- data/ext/openssl/ossl_config.h +4 -7
- data/ext/openssl/ossl_digest.c +31 -62
- data/ext/openssl/ossl_engine.c +18 -27
- data/ext/openssl/ossl_hmac.c +52 -145
- data/ext/openssl/ossl_kdf.c +11 -19
- data/ext/openssl/ossl_ns_spki.c +1 -1
- data/ext/openssl/ossl_ocsp.c +9 -62
- data/ext/openssl/ossl_ocsp.h +3 -3
- data/ext/openssl/ossl_pkcs12.c +21 -3
- data/ext/openssl/ossl_pkcs7.c +45 -78
- data/ext/openssl/ossl_pkcs7.h +16 -0
- data/ext/openssl/ossl_pkey.c +1255 -178
- data/ext/openssl/ossl_pkey.h +40 -77
- data/ext/openssl/ossl_pkey_dh.c +125 -335
- data/ext/openssl/ossl_pkey_dsa.c +93 -398
- data/ext/openssl/ossl_pkey_ec.c +155 -318
- data/ext/openssl/ossl_pkey_rsa.c +105 -484
- data/ext/openssl/ossl_rand.c +2 -40
- data/ext/openssl/ossl_ssl.c +395 -364
- data/ext/openssl/ossl_ssl_session.c +24 -29
- data/ext/openssl/ossl_ts.c +1539 -0
- data/ext/openssl/ossl_ts.h +16 -0
- data/ext/openssl/ossl_x509.c +86 -1
- data/ext/openssl/ossl_x509cert.c +166 -10
- data/ext/openssl/ossl_x509crl.c +10 -7
- data/ext/openssl/ossl_x509ext.c +15 -2
- data/ext/openssl/ossl_x509name.c +16 -5
- data/ext/openssl/ossl_x509req.c +10 -7
- data/ext/openssl/ossl_x509store.c +193 -92
- data/lib/openssl/bn.rb +1 -1
- data/lib/openssl/buffering.rb +42 -17
- data/lib/openssl/cipher.rb +1 -1
- data/lib/openssl/digest.rb +10 -12
- data/lib/openssl/hmac.rb +78 -0
- data/lib/openssl/marshal.rb +30 -0
- data/lib/openssl/pkcs5.rb +1 -1
- data/lib/openssl/pkey.rb +435 -1
- data/lib/openssl/ssl.rb +53 -14
- data/lib/openssl/version.rb +5 -0
- data/lib/openssl/x509.rb +177 -1
- data/lib/openssl.rb +24 -9
- metadata +13 -69
- data/ext/openssl/deprecation.rb +0 -23
- data/ext/openssl/ossl_version.h +0 -15
- data/ext/openssl/ruby_missing.h +0 -24
- data/lib/openssl/config.rb +0 -474
data/ext/openssl/ossl_pkey.c
CHANGED
@@ -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(
|
42
|
+
pkey_new0(VALUE arg)
|
97
43
|
{
|
98
|
-
|
99
|
-
|
44
|
+
EVP_PKEY *pkey = (EVP_PKEY *)arg;
|
45
|
+
VALUE klass, obj;
|
100
46
|
|
101
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
119
|
-
return ossl_ec_new(pkey);
|
58
|
+
case EVP_PKEY_EC: klass = cEC; break;
|
120
59
|
#endif
|
121
|
-
|
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(
|
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
|
-
* *
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
814
|
+
* pkey.compare?(another_pkey) -> true | false
|
299
815
|
*
|
300
|
-
*
|
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
|
-
*
|
309
|
-
*
|
310
|
-
*
|
311
|
-
*
|
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
|
-
|
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
|
-
|
887
|
+
VALUE digest, data, options, sig;
|
888
|
+
const EVP_MD *md = NULL;
|
318
889
|
EVP_MD_CTX *ctx;
|
319
|
-
|
320
|
-
|
321
|
-
int
|
890
|
+
EVP_PKEY_CTX *pctx;
|
891
|
+
size_t siglen;
|
892
|
+
int state;
|
322
893
|
|
323
894
|
pkey = GetPrivPKeyPtr(self);
|
324
|
-
|
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
|
-
|
331
|
-
if (
|
332
|
-
|
333
|
-
|
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 (
|
336
|
-
|
337
|
-
|
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
|
-
|
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
|
-
|
342
|
-
|
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
|
-
*
|
350
|
-
*
|
965
|
+
* call-seq:
|
966
|
+
* pkey.verify(digest, signature, data [, options]) -> true or false
|
351
967
|
*
|
352
|
-
*
|
353
|
-
*
|
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
|
-
*
|
362
|
-
*
|
363
|
-
*
|
364
|
-
*
|
365
|
-
*
|
366
|
-
*
|
367
|
-
*
|
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(
|
988
|
+
ossl_pkey_verify(int argc, VALUE *argv, VALUE self)
|
371
989
|
{
|
372
990
|
EVP_PKEY *pkey;
|
373
|
-
|
991
|
+
VALUE digest, sig, data, options;
|
992
|
+
const EVP_MD *md = NULL;
|
374
993
|
EVP_MD_CTX *ctx;
|
375
|
-
|
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
|
-
|
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
|
-
|
387
|
-
if (
|
388
|
-
|
389
|
-
|
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 (!
|
392
|
-
|
393
|
-
|
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
|
-
|
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
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
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,
|
496
|
-
rb_define_method(cPKey, "verify", ossl_pkey_verify,
|
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
|
|