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