rubysl-openssl 1.0.2 → 2.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/.travis.yml +5 -6
- data/ext/rubysl/openssl/.gitignore +3 -0
- data/ext/rubysl/openssl/deprecation.rb +21 -0
- data/ext/rubysl/openssl/extconf.rb +45 -32
- data/ext/rubysl/openssl/openssl_missing.c +20 -7
- data/ext/rubysl/openssl/openssl_missing.h +22 -15
- data/ext/rubysl/openssl/ossl.c +610 -61
- data/ext/rubysl/openssl/ossl.h +31 -17
- data/ext/rubysl/openssl/ossl_asn1.c +974 -183
- data/ext/rubysl/openssl/ossl_asn1.h +3 -3
- data/ext/rubysl/openssl/ossl_bio.c +4 -3
- data/ext/rubysl/openssl/ossl_bio.h +1 -1
- data/ext/rubysl/openssl/ossl_bn.c +32 -28
- data/ext/rubysl/openssl/ossl_bn.h +1 -1
- data/ext/rubysl/openssl/ossl_cipher.c +494 -93
- data/ext/rubysl/openssl/ossl_cipher.h +1 -1
- data/ext/rubysl/openssl/ossl_config.c +4 -5
- data/ext/rubysl/openssl/ossl_config.h +1 -1
- data/ext/rubysl/openssl/ossl_digest.c +206 -24
- data/ext/rubysl/openssl/ossl_digest.h +1 -1
- data/ext/rubysl/openssl/ossl_engine.c +48 -26
- data/ext/rubysl/openssl/ossl_engine.h +1 -1
- data/ext/rubysl/openssl/ossl_hmac.c +40 -38
- data/ext/rubysl/openssl/ossl_hmac.h +1 -1
- data/ext/rubysl/openssl/ossl_ns_spki.c +157 -25
- data/ext/rubysl/openssl/ossl_ns_spki.h +1 -1
- data/ext/rubysl/openssl/ossl_ocsp.c +57 -40
- data/ext/rubysl/openssl/ossl_ocsp.h +1 -1
- data/ext/rubysl/openssl/ossl_pkcs12.c +15 -13
- data/ext/rubysl/openssl/ossl_pkcs12.h +1 -1
- data/ext/rubysl/openssl/ossl_pkcs5.c +108 -18
- data/ext/rubysl/openssl/ossl_pkcs7.c +44 -37
- data/ext/rubysl/openssl/ossl_pkcs7.h +1 -1
- data/ext/rubysl/openssl/ossl_pkey.c +211 -15
- data/ext/rubysl/openssl/ossl_pkey.h +19 -9
- data/ext/rubysl/openssl/ossl_pkey_dh.c +180 -47
- data/ext/rubysl/openssl/ossl_pkey_dsa.c +184 -47
- data/ext/rubysl/openssl/ossl_pkey_ec.c +177 -93
- data/ext/rubysl/openssl/ossl_pkey_rsa.c +209 -102
- data/ext/rubysl/openssl/ossl_rand.c +15 -15
- data/ext/rubysl/openssl/ossl_rand.h +1 -1
- data/ext/rubysl/openssl/ossl_ssl.c +939 -192
- data/ext/rubysl/openssl/ossl_ssl.h +6 -6
- data/ext/rubysl/openssl/ossl_ssl_session.c +78 -62
- data/ext/rubysl/openssl/ossl_version.h +2 -2
- data/ext/rubysl/openssl/ossl_x509.c +1 -1
- data/ext/rubysl/openssl/ossl_x509.h +1 -1
- data/ext/rubysl/openssl/ossl_x509attr.c +20 -19
- data/ext/rubysl/openssl/ossl_x509cert.c +169 -67
- data/ext/rubysl/openssl/ossl_x509crl.c +41 -39
- data/ext/rubysl/openssl/ossl_x509ext.c +51 -38
- data/ext/rubysl/openssl/ossl_x509name.c +139 -29
- data/ext/rubysl/openssl/ossl_x509req.c +42 -40
- data/ext/rubysl/openssl/ossl_x509revoked.c +20 -20
- data/ext/rubysl/openssl/ossl_x509store.c +99 -47
- data/ext/rubysl/openssl/ruby_missing.h +3 -16
- data/lib/openssl/bn.rb +19 -19
- data/lib/openssl/buffering.rb +222 -14
- data/lib/openssl/cipher.rb +20 -20
- data/lib/openssl/config.rb +1 -4
- data/lib/openssl/digest.rb +47 -19
- data/lib/openssl/ssl.rb +197 -1
- data/lib/openssl/x509.rb +162 -1
- data/lib/rubysl/openssl.rb +4 -8
- data/lib/rubysl/openssl/version.rb +1 -1
- data/rubysl-openssl.gemspec +1 -2
- metadata +16 -34
- data/ext/rubysl/openssl/extconf.h +0 -50
- data/lib/openssl/net/ftptls.rb +0 -53
- data/lib/openssl/net/telnets.rb +0 -251
- data/lib/openssl/pkcs7.rb +0 -25
- data/lib/openssl/ssl-internal.rb +0 -187
- data/lib/openssl/x509-internal.rb +0 -153
@@ -1,5 +1,5 @@
|
|
1
1
|
/*
|
2
|
-
* $Id
|
2
|
+
* $Id$
|
3
3
|
* 'OpenSSL for Ruby' project
|
4
4
|
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
5
5
|
* All rights reserved.
|
@@ -13,8 +13,8 @@
|
|
13
13
|
#include "ossl.h"
|
14
14
|
|
15
15
|
#define GetPKeyDSA(obj, pkey) do { \
|
16
|
-
GetPKey(obj, pkey); \
|
17
|
-
if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DSA) { /* PARANOIA? */ \
|
16
|
+
GetPKey((obj), (pkey)); \
|
17
|
+
if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_DSA) { /* PARANOIA? */ \
|
18
18
|
ossl_raise(rb_eRuntimeError, "THIS IS NOT A DSA!"); \
|
19
19
|
} \
|
20
20
|
} while (0)
|
@@ -36,7 +36,7 @@ dsa_instance(VALUE klass, DSA *dsa)
|
|
36
36
|
{
|
37
37
|
EVP_PKEY *pkey;
|
38
38
|
VALUE obj;
|
39
|
-
|
39
|
+
|
40
40
|
if (!dsa) {
|
41
41
|
return Qfalse;
|
42
42
|
}
|
@@ -75,9 +75,69 @@ ossl_dsa_new(EVP_PKEY *pkey)
|
|
75
75
|
/*
|
76
76
|
* Private
|
77
77
|
*/
|
78
|
+
#if defined(HAVE_DSA_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB
|
79
|
+
struct dsa_blocking_gen_arg {
|
80
|
+
DSA *dsa;
|
81
|
+
int size;
|
82
|
+
unsigned char* seed;
|
83
|
+
int seed_len;
|
84
|
+
int *counter;
|
85
|
+
unsigned long *h;
|
86
|
+
BN_GENCB *cb;
|
87
|
+
int result;
|
88
|
+
};
|
89
|
+
|
90
|
+
static void *
|
91
|
+
dsa_blocking_gen(void *arg)
|
92
|
+
{
|
93
|
+
struct dsa_blocking_gen_arg *gen = (struct dsa_blocking_gen_arg *)arg;
|
94
|
+
gen->result = DSA_generate_parameters_ex(gen->dsa, gen->size, gen->seed, gen->seed_len, gen->counter, gen->h, gen->cb);
|
95
|
+
return 0;
|
96
|
+
}
|
97
|
+
#endif
|
98
|
+
|
78
99
|
static DSA *
|
79
100
|
dsa_generate(int size)
|
80
101
|
{
|
102
|
+
#if defined(HAVE_DSA_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB
|
103
|
+
BN_GENCB cb;
|
104
|
+
struct ossl_generate_cb_arg cb_arg;
|
105
|
+
struct dsa_blocking_gen_arg gen_arg;
|
106
|
+
DSA *dsa = DSA_new();
|
107
|
+
unsigned char seed[20];
|
108
|
+
int seed_len = 20, counter;
|
109
|
+
unsigned long h;
|
110
|
+
|
111
|
+
if (!dsa) return 0;
|
112
|
+
if (!RAND_bytes(seed, seed_len)) {
|
113
|
+
DSA_free(dsa);
|
114
|
+
return 0;
|
115
|
+
}
|
116
|
+
|
117
|
+
memset(&cb_arg, 0, sizeof(struct ossl_generate_cb_arg));
|
118
|
+
if (rb_block_given_p())
|
119
|
+
cb_arg.yield = 1;
|
120
|
+
BN_GENCB_set(&cb, ossl_generate_cb_2, &cb_arg);
|
121
|
+
gen_arg.dsa = dsa;
|
122
|
+
gen_arg.size = size;
|
123
|
+
gen_arg.seed = seed;
|
124
|
+
gen_arg.seed_len = seed_len;
|
125
|
+
gen_arg.counter = &counter;
|
126
|
+
gen_arg.h = &h;
|
127
|
+
gen_arg.cb = &cb;
|
128
|
+
if (cb_arg.yield == 1) {
|
129
|
+
/* we cannot release GVL when callback proc is supplied */
|
130
|
+
dsa_blocking_gen(&gen_arg);
|
131
|
+
} else {
|
132
|
+
/* there's a chance to unblock */
|
133
|
+
rb_thread_call_without_gvl(dsa_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg);
|
134
|
+
}
|
135
|
+
if (!gen_arg.result) {
|
136
|
+
DSA_free(dsa);
|
137
|
+
if (cb_arg.state) rb_jump_tag(cb_arg.state);
|
138
|
+
return 0;
|
139
|
+
}
|
140
|
+
#else
|
81
141
|
DSA *dsa;
|
82
142
|
unsigned char seed[20];
|
83
143
|
int seed_len = 20, counter;
|
@@ -87,9 +147,9 @@ dsa_generate(int size)
|
|
87
147
|
return 0;
|
88
148
|
}
|
89
149
|
dsa = DSA_generate_parameters(size, seed, seed_len, &counter, &h,
|
90
|
-
rb_block_given_p() ? ossl_generate_cb : NULL,
|
91
|
-
NULL);
|
150
|
+
rb_block_given_p() ? ossl_generate_cb : NULL, NULL);
|
92
151
|
if(!dsa) return 0;
|
152
|
+
#endif
|
93
153
|
|
94
154
|
if (!DSA_generate_key(dsa)) {
|
95
155
|
DSA_free(dsa);
|
@@ -103,8 +163,11 @@ dsa_generate(int size)
|
|
103
163
|
* call-seq:
|
104
164
|
* DSA.generate(size) -> dsa
|
105
165
|
*
|
106
|
-
*
|
107
|
-
*
|
166
|
+
* Creates a new DSA instance by generating a private/public key pair
|
167
|
+
* from scratch.
|
168
|
+
*
|
169
|
+
* === Parameters
|
170
|
+
* * +size+ is an integer representing the desired key size.
|
108
171
|
*
|
109
172
|
*/
|
110
173
|
static VALUE
|
@@ -125,16 +188,18 @@ ossl_dsa_s_generate(VALUE klass, VALUE size)
|
|
125
188
|
* call-seq:
|
126
189
|
* DSA.new([size | string [, pass]) -> dsa
|
127
190
|
*
|
128
|
-
*
|
129
|
-
* * +size+ is an integer representing the desired key size.
|
130
|
-
* * +string+ contains a DER or PEM encoded key.
|
131
|
-
* * +pass+ is a string that contains a optional password.
|
191
|
+
* Creates a new DSA instance by reading an existing key from +string+.
|
132
192
|
*
|
133
|
-
*
|
134
|
-
*
|
135
|
-
*
|
136
|
-
*
|
137
|
-
*
|
193
|
+
* === Parameters
|
194
|
+
* * +size+ is an integer representing the desired key size.
|
195
|
+
* * +string+ contains a DER or PEM encoded key.
|
196
|
+
* * +pass+ is a string that contains an optional password.
|
197
|
+
*
|
198
|
+
* === Examples
|
199
|
+
* DSA.new -> dsa
|
200
|
+
* DSA.new(1024) -> dsa
|
201
|
+
* DSA.new(File.read('dsa.pem')) -> dsa
|
202
|
+
* DSA.new(File.read('dsa.pem'), 'mypassword') -> dsa
|
138
203
|
*
|
139
204
|
*/
|
140
205
|
static VALUE
|
@@ -145,7 +210,7 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
|
|
145
210
|
BIO *in;
|
146
211
|
char *passwd = NULL;
|
147
212
|
VALUE arg, pass;
|
148
|
-
|
213
|
+
|
149
214
|
GetPKey(self, pkey);
|
150
215
|
if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
|
151
216
|
dsa = DSA_new();
|
@@ -161,23 +226,26 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
|
|
161
226
|
in = ossl_obj2bio(arg);
|
162
227
|
dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
|
163
228
|
if (!dsa) {
|
164
|
-
|
165
|
-
dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL);
|
166
|
-
}
|
167
|
-
if (!dsa) {
|
168
|
-
BIO_reset(in);
|
229
|
+
OSSL_BIO_reset(in);
|
169
230
|
dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL);
|
170
231
|
}
|
171
232
|
if (!dsa) {
|
172
|
-
|
233
|
+
OSSL_BIO_reset(in);
|
173
234
|
dsa = d2i_DSAPrivateKey_bio(in, NULL);
|
174
235
|
}
|
175
236
|
if (!dsa) {
|
176
|
-
|
237
|
+
OSSL_BIO_reset(in);
|
177
238
|
dsa = d2i_DSA_PUBKEY_bio(in, NULL);
|
178
239
|
}
|
240
|
+
if (!dsa) {
|
241
|
+
OSSL_BIO_reset(in);
|
242
|
+
dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL);
|
243
|
+
}
|
179
244
|
BIO_free(in);
|
180
|
-
if (!dsa)
|
245
|
+
if (!dsa) {
|
246
|
+
ERR_clear_error();
|
247
|
+
ossl_raise(eDSAError, "Neither PUB key nor PRIV key");
|
248
|
+
}
|
181
249
|
}
|
182
250
|
if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
|
183
251
|
DSA_free(dsa);
|
@@ -191,6 +259,8 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
|
|
191
259
|
* call-seq:
|
192
260
|
* dsa.public? -> true | false
|
193
261
|
*
|
262
|
+
* Indicates whether this DSA instance has a public key associated with it or
|
263
|
+
* not. The public key may be retrieved with DSA#public_key.
|
194
264
|
*/
|
195
265
|
static VALUE
|
196
266
|
ossl_dsa_is_public(VALUE self)
|
@@ -206,14 +276,16 @@ ossl_dsa_is_public(VALUE self)
|
|
206
276
|
* call-seq:
|
207
277
|
* dsa.private? -> true | false
|
208
278
|
*
|
279
|
+
* Indicates whether this DSA instance has a private key associated with it or
|
280
|
+
* not. The private key may be retrieved with DSA#private_key.
|
209
281
|
*/
|
210
282
|
static VALUE
|
211
283
|
ossl_dsa_is_private(VALUE self)
|
212
284
|
{
|
213
285
|
EVP_PKEY *pkey;
|
214
|
-
|
286
|
+
|
215
287
|
GetPKeyDSA(self, pkey);
|
216
|
-
|
288
|
+
|
217
289
|
return (DSA_PRIVATE(self, pkey->pkey.dsa)) ? Qtrue : Qfalse;
|
218
290
|
}
|
219
291
|
|
@@ -221,13 +293,15 @@ ossl_dsa_is_private(VALUE self)
|
|
221
293
|
* call-seq:
|
222
294
|
* dsa.to_pem([cipher, password]) -> aString
|
223
295
|
*
|
224
|
-
*
|
225
|
-
* +cipher+ is an OpenSSL::Cipher.
|
226
|
-
* +password+ is a string containing your password.
|
296
|
+
* Encodes this DSA to its PEM encoding.
|
227
297
|
*
|
228
|
-
*
|
229
|
-
*
|
230
|
-
*
|
298
|
+
* === Parameters
|
299
|
+
* * +cipher+ is an OpenSSL::Cipher.
|
300
|
+
* * +password+ is a string containing your password.
|
301
|
+
*
|
302
|
+
* === Examples
|
303
|
+
* DSA.to_pem -> aString
|
304
|
+
* DSA.to_pem(cipher, 'mypassword') -> aString
|
231
305
|
*
|
232
306
|
*/
|
233
307
|
static VALUE
|
@@ -244,7 +318,10 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self)
|
|
244
318
|
if (!NIL_P(cipher)) {
|
245
319
|
ciph = GetCipherPtr(cipher);
|
246
320
|
if (!NIL_P(pass)) {
|
247
|
-
|
321
|
+
StringValue(pass);
|
322
|
+
if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN)
|
323
|
+
ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long");
|
324
|
+
passwd = RSTRING_PTR(pass);
|
248
325
|
}
|
249
326
|
}
|
250
327
|
if (!(out = BIO_new(BIO_s_mem()))) {
|
@@ -257,7 +334,7 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self)
|
|
257
334
|
ossl_raise(eDSAError, NULL);
|
258
335
|
}
|
259
336
|
} else {
|
260
|
-
if (!
|
337
|
+
if (!PEM_write_bio_DSA_PUBKEY(out, pkey->pkey.dsa)) {
|
261
338
|
BIO_free(out);
|
262
339
|
ossl_raise(eDSAError, NULL);
|
263
340
|
}
|
@@ -271,6 +348,8 @@ ossl_dsa_export(int argc, VALUE *argv, VALUE self)
|
|
271
348
|
* call-seq:
|
272
349
|
* dsa.to_der -> aString
|
273
350
|
*
|
351
|
+
* Encodes this DSA to its DER encoding.
|
352
|
+
*
|
274
353
|
*/
|
275
354
|
static VALUE
|
276
355
|
ossl_dsa_to_der(VALUE self)
|
@@ -289,7 +368,7 @@ ossl_dsa_to_der(VALUE self)
|
|
289
368
|
if((len = i2d_func(pkey->pkey.dsa, NULL)) <= 0)
|
290
369
|
ossl_raise(eDSAError, NULL);
|
291
370
|
str = rb_str_new(0, len);
|
292
|
-
p = RSTRING_PTR(str);
|
371
|
+
p = (unsigned char *)RSTRING_PTR(str);
|
293
372
|
if(i2d_func(pkey->pkey.dsa, &p) < 0)
|
294
373
|
ossl_raise(eDSAError, NULL);
|
295
374
|
ossl_str_adjust(str, p);
|
@@ -320,7 +399,7 @@ ossl_dsa_get_params(VALUE self)
|
|
320
399
|
rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dsa->g));
|
321
400
|
rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dsa->pub_key));
|
322
401
|
rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dsa->priv_key));
|
323
|
-
|
402
|
+
|
324
403
|
return hash;
|
325
404
|
}
|
326
405
|
|
@@ -356,7 +435,18 @@ ossl_dsa_to_text(VALUE self)
|
|
356
435
|
* call-seq:
|
357
436
|
* dsa.public_key -> aDSA
|
358
437
|
*
|
359
|
-
*
|
438
|
+
* Returns a new DSA instance that carries just the public key information.
|
439
|
+
* If the current instance has also private key information, this will no
|
440
|
+
* longer be present in the new instance. This feature is helpful for
|
441
|
+
* publishing the public key information without leaking any of the private
|
442
|
+
* information.
|
443
|
+
*
|
444
|
+
* === Example
|
445
|
+
* dsa = OpenSSL::PKey::DSA.new(2048) # has public and private information
|
446
|
+
* pub_key = dsa.public_key # has only the public part available
|
447
|
+
* pub_key_der = pub_key.to_der # it's safe to publish this
|
448
|
+
*
|
449
|
+
*
|
360
450
|
*/
|
361
451
|
static VALUE
|
362
452
|
ossl_dsa_to_public_key(VALUE self)
|
@@ -364,7 +454,7 @@ ossl_dsa_to_public_key(VALUE self)
|
|
364
454
|
EVP_PKEY *pkey;
|
365
455
|
DSA *dsa;
|
366
456
|
VALUE obj;
|
367
|
-
|
457
|
+
|
368
458
|
GetPKeyDSA(self, pkey);
|
369
459
|
/* err check performed by dsa_instance */
|
370
460
|
dsa = DSAPublicKey_dup(pkey->pkey.dsa);
|
@@ -382,12 +472,26 @@ ossl_dsa_to_public_key(VALUE self)
|
|
382
472
|
* call-seq:
|
383
473
|
* dsa.syssign(string) -> aString
|
384
474
|
*
|
475
|
+
* Computes and returns the DSA signature of +string+, where +string+ is
|
476
|
+
* expected to be an already-computed message digest of the original input
|
477
|
+
* data. The signature is issued using the private key of this DSA instance.
|
478
|
+
*
|
479
|
+
* === Parameters
|
480
|
+
* * +string+ is a message digest of the original input data to be signed
|
481
|
+
*
|
482
|
+
* === Example
|
483
|
+
* dsa = OpenSSL::PKey::DSA.new(2048)
|
484
|
+
* doc = "Sign me"
|
485
|
+
* digest = OpenSSL::Digest::SHA1.digest(doc)
|
486
|
+
* sig = dsa.syssign(digest)
|
487
|
+
*
|
488
|
+
*
|
385
489
|
*/
|
386
490
|
static VALUE
|
387
491
|
ossl_dsa_sign(VALUE self, VALUE data)
|
388
492
|
{
|
389
493
|
EVP_PKEY *pkey;
|
390
|
-
int buf_len;
|
494
|
+
unsigned int buf_len;
|
391
495
|
VALUE str;
|
392
496
|
|
393
497
|
GetPKeyDSA(self, pkey);
|
@@ -396,7 +500,8 @@ ossl_dsa_sign(VALUE self, VALUE data)
|
|
396
500
|
ossl_raise(eDSAError, "Private DSA key needed!");
|
397
501
|
}
|
398
502
|
str = rb_str_new(0, ossl_dsa_buf_size(pkey));
|
399
|
-
if (!DSA_sign(0, RSTRING_PTR(data),
|
503
|
+
if (!DSA_sign(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
|
504
|
+
(unsigned char *)RSTRING_PTR(str),
|
400
505
|
&buf_len, pkey->pkey.dsa)) { /* type is ignored (0) */
|
401
506
|
ossl_raise(eDSAError, NULL);
|
402
507
|
}
|
@@ -409,6 +514,20 @@ ossl_dsa_sign(VALUE self, VALUE data)
|
|
409
514
|
* call-seq:
|
410
515
|
* dsa.sysverify(digest, sig) -> true | false
|
411
516
|
*
|
517
|
+
* Verifies whether the signature is valid given the message digest input. It
|
518
|
+
* does so by validating +sig+ using the public key of this DSA instance.
|
519
|
+
*
|
520
|
+
* === Parameters
|
521
|
+
* * +digest+ is a message digest of the original input data to be signed
|
522
|
+
* * +sig+ is a DSA signature value
|
523
|
+
*
|
524
|
+
* === Example
|
525
|
+
* dsa = OpenSSL::PKey::DSA.new(2048)
|
526
|
+
* doc = "Sign me"
|
527
|
+
* digest = OpenSSL::Digest::SHA1.digest(doc)
|
528
|
+
* sig = dsa.syssign(digest)
|
529
|
+
* puts dsa.sysverify(digest, sig) # => true
|
530
|
+
*
|
412
531
|
*/
|
413
532
|
static VALUE
|
414
533
|
ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
|
@@ -420,8 +539,8 @@ ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
|
|
420
539
|
StringValue(digest);
|
421
540
|
StringValue(sig);
|
422
541
|
/* type is ignored (0) */
|
423
|
-
ret = DSA_verify(0, RSTRING_PTR(digest),
|
424
|
-
RSTRING_PTR(sig),
|
542
|
+
ret = DSA_verify(0, (unsigned char *)RSTRING_PTR(digest), RSTRING_LENINT(digest),
|
543
|
+
(unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), pkey->pkey.dsa);
|
425
544
|
if (ret < 0) {
|
426
545
|
ossl_raise(eDSAError, NULL);
|
427
546
|
}
|
@@ -444,15 +563,33 @@ OSSL_PKEY_BN(dsa, priv_key)
|
|
444
563
|
void
|
445
564
|
Init_ossl_dsa()
|
446
565
|
{
|
447
|
-
#if 0
|
448
|
-
mOSSL = rb_define_module("OpenSSL");
|
566
|
+
#if 0
|
567
|
+
mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL and mPKey */
|
449
568
|
mPKey = rb_define_module_under(mOSSL, "PKey");
|
450
569
|
#endif
|
451
570
|
|
571
|
+
/* Document-class: OpenSSL::PKey::DSAError
|
572
|
+
*
|
573
|
+
* Generic exception that is raised if an operation on a DSA PKey
|
574
|
+
* fails unexpectedly or in case an instantiation of an instance of DSA
|
575
|
+
* fails due to non-conformant input data.
|
576
|
+
*/
|
452
577
|
eDSAError = rb_define_class_under(mPKey, "DSAError", ePKeyError);
|
453
578
|
|
579
|
+
/* Document-class: OpenSSL::PKey::DSA
|
580
|
+
*
|
581
|
+
* DSA, the Digital Signature Algorithm, is specified in NIST's
|
582
|
+
* FIPS 186-3. It is an asymmetric public key algorithm that may be used
|
583
|
+
* similar to e.g. RSA.
|
584
|
+
* Please note that for OpenSSL versions prior to 1.0.0 the digest
|
585
|
+
* algorithms OpenSSL::Digest::DSS (equivalent to SHA) or
|
586
|
+
* OpenSSL::Digest::DSS1 (equivalent to SHA-1) must be used for issuing
|
587
|
+
* signatures with a DSA key using OpenSSL::PKey#sign.
|
588
|
+
* Starting with OpenSSL 1.0.0, digest algorithms are no longer restricted,
|
589
|
+
* any Digest may be used for signing.
|
590
|
+
*/
|
454
591
|
cDSA = rb_define_class_under(mPKey, "DSA", cPKey);
|
455
|
-
|
592
|
+
|
456
593
|
rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1);
|
457
594
|
rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1);
|
458
595
|
|
@@ -22,70 +22,70 @@ typedef struct {
|
|
22
22
|
|
23
23
|
|
24
24
|
#define GetPKeyEC(obj, pkey) do { \
|
25
|
-
GetPKey(obj, pkey); \
|
26
|
-
if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) { \
|
25
|
+
GetPKey((obj), (pkey)); \
|
26
|
+
if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_EC) { \
|
27
27
|
ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \
|
28
28
|
} \
|
29
29
|
} while (0)
|
30
30
|
|
31
31
|
#define SafeGet_ec_group(obj, group) do { \
|
32
|
-
OSSL_Check_Kind(obj, cEC_GROUP); \
|
33
|
-
Data_Get_Struct(obj, ossl_ec_group, group); \
|
32
|
+
OSSL_Check_Kind((obj), cEC_GROUP); \
|
33
|
+
Data_Get_Struct((obj), ossl_ec_group, (group)); \
|
34
34
|
} while(0)
|
35
35
|
|
36
36
|
#define Get_EC_KEY(obj, key) do { \
|
37
37
|
EVP_PKEY *pkey; \
|
38
|
-
GetPKeyEC(obj, pkey); \
|
39
|
-
key = pkey->pkey.ec; \
|
38
|
+
GetPKeyEC((obj), pkey); \
|
39
|
+
(key) = pkey->pkey.ec; \
|
40
40
|
} while(0)
|
41
41
|
|
42
42
|
#define Require_EC_KEY(obj, key) do { \
|
43
|
-
Get_EC_KEY(obj, key); \
|
44
|
-
if (key == NULL) \
|
45
|
-
|
43
|
+
Get_EC_KEY((obj), (key)); \
|
44
|
+
if ((key) == NULL) \
|
45
|
+
ossl_raise(eECError, "EC_KEY is not initialized"); \
|
46
46
|
} while(0)
|
47
47
|
|
48
48
|
#define SafeRequire_EC_KEY(obj, key) do { \
|
49
|
-
OSSL_Check_Kind(obj, cEC); \
|
50
|
-
Require_EC_KEY(obj, key); \
|
49
|
+
OSSL_Check_Kind((obj), cEC); \
|
50
|
+
Require_EC_KEY((obj), (key)); \
|
51
51
|
} while (0)
|
52
52
|
|
53
53
|
#define Get_EC_GROUP(obj, g) do { \
|
54
54
|
ossl_ec_group *ec_group; \
|
55
|
-
Data_Get_Struct(obj, ossl_ec_group, ec_group); \
|
55
|
+
Data_Get_Struct((obj), ossl_ec_group, ec_group); \
|
56
56
|
if (ec_group == NULL) \
|
57
|
-
|
58
|
-
g = ec_group->group; \
|
57
|
+
ossl_raise(eEC_GROUP, "missing ossl_ec_group structure"); \
|
58
|
+
(g) = ec_group->group; \
|
59
59
|
} while(0)
|
60
60
|
|
61
61
|
#define Require_EC_GROUP(obj, group) do { \
|
62
|
-
Get_EC_GROUP(obj, group); \
|
63
|
-
if (group == NULL) \
|
64
|
-
|
62
|
+
Get_EC_GROUP((obj), (group)); \
|
63
|
+
if ((group) == NULL) \
|
64
|
+
ossl_raise(eEC_GROUP, "EC_GROUP is not initialized"); \
|
65
65
|
} while(0)
|
66
66
|
|
67
67
|
#define SafeRequire_EC_GROUP(obj, group) do { \
|
68
|
-
OSSL_Check_Kind(obj, cEC_GROUP); \
|
69
|
-
Require_EC_GROUP(obj, group); \
|
68
|
+
OSSL_Check_Kind((obj), cEC_GROUP); \
|
69
|
+
Require_EC_GROUP((obj), (group)); \
|
70
70
|
} while(0)
|
71
71
|
|
72
72
|
#define Get_EC_POINT(obj, p) do { \
|
73
73
|
ossl_ec_point *ec_point; \
|
74
|
-
Data_Get_Struct(obj, ossl_ec_point, ec_point); \
|
74
|
+
Data_Get_Struct((obj), ossl_ec_point, ec_point); \
|
75
75
|
if (ec_point == NULL) \
|
76
|
-
|
77
|
-
p = ec_point->point; \
|
76
|
+
ossl_raise(eEC_POINT, "missing ossl_ec_point structure"); \
|
77
|
+
(p) = ec_point->point; \
|
78
78
|
} while(0)
|
79
79
|
|
80
80
|
#define Require_EC_POINT(obj, point) do { \
|
81
|
-
Get_EC_POINT(obj, point); \
|
82
|
-
if (point == NULL) \
|
83
|
-
|
81
|
+
Get_EC_POINT((obj), (point)); \
|
82
|
+
if ((point) == NULL) \
|
83
|
+
ossl_raise(eEC_POINT, "EC_POINT is not initialized"); \
|
84
84
|
} while(0)
|
85
85
|
|
86
86
|
#define SafeRequire_EC_POINT(obj, point) do { \
|
87
|
-
OSSL_Check_Kind(obj, cEC_POINT); \
|
88
|
-
Require_EC_POINT(obj, point); \
|
87
|
+
OSSL_Check_Kind((obj), cEC_POINT); \
|
88
|
+
Require_EC_POINT((obj), (point)); \
|
89
89
|
} while(0)
|
90
90
|
|
91
91
|
VALUE cEC;
|
@@ -110,7 +110,7 @@ static VALUE ec_instance(VALUE klass, EC_KEY *ec)
|
|
110
110
|
{
|
111
111
|
EVP_PKEY *pkey;
|
112
112
|
VALUE obj;
|
113
|
-
|
113
|
+
|
114
114
|
if (!ec) {
|
115
115
|
return Qfalse;
|
116
116
|
}
|
@@ -152,6 +152,7 @@ VALUE ossl_ec_new(EVP_PKEY *pkey)
|
|
152
152
|
* OpenSSL::PKey::EC.new(ec_group)
|
153
153
|
* OpenSSL::PKey::EC.new("secp112r1")
|
154
154
|
* OpenSSL::PKey::EC.new(pem_string)
|
155
|
+
* OpenSSL::PKey::EC.new(pem_string [, pwd])
|
155
156
|
* OpenSSL::PKey::EC.new(der_string)
|
156
157
|
*
|
157
158
|
* See the OpenSSL documentation for:
|
@@ -163,10 +164,11 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
|
|
163
164
|
EC_KEY *ec = NULL;
|
164
165
|
VALUE arg, pass;
|
165
166
|
VALUE group = Qnil;
|
166
|
-
|
167
|
+
char *passwd = NULL;
|
168
|
+
|
167
169
|
GetPKey(self, pkey);
|
168
170
|
if (pkey->pkey.ec)
|
169
|
-
|
171
|
+
ossl_raise(eECError, "EC_KEY already initialized");
|
170
172
|
|
171
173
|
rb_scan_args(argc, argv, "02", &arg, &pass);
|
172
174
|
|
@@ -184,26 +186,30 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
|
|
184
186
|
} else {
|
185
187
|
BIO *in = ossl_obj2bio(arg);
|
186
188
|
|
187
|
-
|
189
|
+
if (!NIL_P(pass)) {
|
190
|
+
passwd = StringValuePtr(pass);
|
191
|
+
}
|
192
|
+
ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
|
188
193
|
if (!ec) {
|
189
|
-
|
190
|
-
|
194
|
+
OSSL_BIO_reset(in);
|
195
|
+
ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, passwd);
|
191
196
|
}
|
192
197
|
if (!ec) {
|
193
|
-
|
198
|
+
OSSL_BIO_reset(in);
|
194
199
|
ec = d2i_ECPrivateKey_bio(in, NULL);
|
195
200
|
}
|
196
201
|
if (!ec) {
|
197
|
-
|
202
|
+
OSSL_BIO_reset(in);
|
198
203
|
ec = d2i_EC_PUBKEY_bio(in, NULL);
|
199
204
|
}
|
200
205
|
|
201
206
|
BIO_free(in);
|
202
207
|
|
203
208
|
if (ec == NULL) {
|
204
|
-
const char *name =
|
209
|
+
const char *name = StringValueCStr(arg);
|
205
210
|
int nid = OBJ_sn2nid(name);
|
206
211
|
|
212
|
+
(void)ERR_get_error();
|
207
213
|
if (nid == NID_undef)
|
208
214
|
ossl_raise(eECError, "unknown curve name (%s)\n", name);
|
209
215
|
|
@@ -274,7 +280,7 @@ static VALUE ossl_ec_key_get_group(VALUE self)
|
|
274
280
|
* the group.
|
275
281
|
*
|
276
282
|
* Setting the group will immediately destroy any previously assigned group object.
|
277
|
-
* The group is internally copied by OpenSSL. Modifying the original group after
|
283
|
+
* The group is internally copied by OpenSSL. Modifying the original group after
|
278
284
|
* assignment will not effect the internal key structure.
|
279
285
|
* (your changes may be lost). BE CAREFUL.
|
280
286
|
*
|
@@ -457,22 +463,19 @@ static VALUE ossl_ec_key_is_private_key(VALUE self)
|
|
457
463
|
return (EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse);
|
458
464
|
}
|
459
465
|
|
460
|
-
static VALUE ossl_ec_key_to_string(VALUE self, int format)
|
466
|
+
static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int format)
|
461
467
|
{
|
462
468
|
EC_KEY *ec;
|
463
469
|
BIO *out;
|
464
470
|
int i = -1;
|
465
471
|
int private = 0;
|
466
|
-
#if 0 /* unused now */
|
467
|
-
EVP_CIPHER *cipher = NULL;
|
468
472
|
char *password = NULL;
|
469
|
-
#endif
|
470
473
|
VALUE str;
|
471
474
|
|
472
475
|
Require_EC_KEY(self, ec);
|
473
476
|
|
474
477
|
if (EC_KEY_get0_public_key(ec) == NULL)
|
475
|
-
|
478
|
+
ossl_raise(eECError, "can't export - no public key set");
|
476
479
|
|
477
480
|
if (EC_KEY_check_key(ec) != 1)
|
478
481
|
ossl_raise(eECError, "can't export - EC_KEY_check_key failed");
|
@@ -486,44 +489,36 @@ static VALUE ossl_ec_key_to_string(VALUE self, int format)
|
|
486
489
|
switch(format) {
|
487
490
|
case EXPORT_PEM:
|
488
491
|
if (private) {
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
492
|
+
const EVP_CIPHER *cipher;
|
493
|
+
if (!NIL_P(ciph)) {
|
494
|
+
cipher = GetCipherPtr(ciph);
|
495
|
+
if (!NIL_P(pass)) {
|
496
|
+
StringValue(pass);
|
497
|
+
if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN)
|
498
|
+
ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long");
|
499
|
+
password = RSTRING_PTR(pass);
|
500
|
+
}
|
501
|
+
}
|
502
|
+
else {
|
503
|
+
cipher = NULL;
|
504
|
+
}
|
493
505
|
i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, NULL, password);
|
494
|
-
#endif
|
495
|
-
i = PEM_write_bio_ECPrivateKey(out, ec, NULL, NULL, 0, NULL, NULL);
|
496
506
|
} else {
|
497
|
-
#if 0 /* unused now */
|
498
|
-
if (cipher || password)
|
499
|
-
rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
|
500
|
-
#endif
|
501
|
-
|
502
507
|
i = PEM_write_bio_EC_PUBKEY(out, ec);
|
503
508
|
}
|
504
509
|
|
505
510
|
break;
|
506
511
|
case EXPORT_DER:
|
507
512
|
if (private) {
|
508
|
-
#if 0 /* unused now */
|
509
|
-
if (cipher || password)
|
510
|
-
rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
|
511
|
-
#endif
|
512
|
-
|
513
513
|
i = i2d_ECPrivateKey_bio(out, ec);
|
514
514
|
} else {
|
515
|
-
#if 0 /* unused now */
|
516
|
-
if (cipher || password)
|
517
|
-
rb_raise(rb_eArgError, "encryption is not supported when exporting this key type");
|
518
|
-
#endif
|
519
|
-
|
520
515
|
i = i2d_EC_PUBKEY_bio(out, ec);
|
521
516
|
}
|
522
517
|
|
523
518
|
break;
|
524
519
|
default:
|
525
520
|
BIO_free(out);
|
526
|
-
|
521
|
+
ossl_raise(rb_eRuntimeError, "unknown format (internal error)");
|
527
522
|
}
|
528
523
|
|
529
524
|
if (i != 1) {
|
@@ -538,13 +533,21 @@ static VALUE ossl_ec_key_to_string(VALUE self, int format)
|
|
538
533
|
|
539
534
|
/*
|
540
535
|
* call-seq:
|
541
|
-
* key.
|
536
|
+
* key.export => String
|
537
|
+
* key.export(cipher, pass_phrase) => String
|
538
|
+
*
|
539
|
+
* Outputs the EC key in PEM encoding. If +cipher+ and +pass_phrase+ are
|
540
|
+
* given they will be used to encrypt the key. +cipher+ must be an
|
541
|
+
* OpenSSL::Cipher::Cipher instance. Note that encryption will only be
|
542
|
+
* effective for a private key, public keys will always be encoded in plain
|
543
|
+
* text.
|
542
544
|
*
|
543
|
-
* See the OpenSSL documentation for PEM_write_bio_ECPrivateKey()
|
544
545
|
*/
|
545
|
-
static VALUE
|
546
|
+
static VALUE ossl_ec_key_export(int argc, VALUE *argv, VALUE self)
|
546
547
|
{
|
547
|
-
|
548
|
+
VALUE cipher, passwd;
|
549
|
+
rb_scan_args(argc, argv, "02", &cipher, &passwd);
|
550
|
+
return ossl_ec_key_to_string(self, cipher, passwd, EXPORT_PEM);
|
548
551
|
}
|
549
552
|
|
550
553
|
/*
|
@@ -555,7 +558,7 @@ static VALUE ossl_ec_key_to_pem(VALUE self)
|
|
555
558
|
*/
|
556
559
|
static VALUE ossl_ec_key_to_der(VALUE self)
|
557
560
|
{
|
558
|
-
return ossl_ec_key_to_string(self, EXPORT_DER);
|
561
|
+
return ossl_ec_key_to_string(self, Qnil, Qnil, EXPORT_DER);
|
559
562
|
}
|
560
563
|
|
561
564
|
/*
|
@@ -671,7 +674,7 @@ static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data)
|
|
671
674
|
ossl_raise(eECError, "Private EC key needed!");
|
672
675
|
|
673
676
|
str = rb_str_new(0, ECDSA_size(ec) + 16);
|
674
|
-
if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data),
|
677
|
+
if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1)
|
675
678
|
ossl_raise(eECError, "ECDSA_sign");
|
676
679
|
|
677
680
|
rb_str_resize(str, buf_len);
|
@@ -693,13 +696,15 @@ static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
|
|
693
696
|
StringValue(data);
|
694
697
|
StringValue(sig);
|
695
698
|
|
696
|
-
switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data),
|
699
|
+
switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(sig), (int)RSTRING_LEN(sig), ec)) {
|
697
700
|
case 1: return Qtrue;
|
698
701
|
case 0: return Qfalse;
|
699
702
|
default: break;
|
700
703
|
}
|
701
704
|
|
702
705
|
ossl_raise(eECError, "ECDSA_verify");
|
706
|
+
|
707
|
+
UNREACHABLE;
|
703
708
|
}
|
704
709
|
|
705
710
|
static void ossl_ec_group_free(ossl_ec_group *ec_group)
|
@@ -743,7 +748,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
|
|
743
748
|
|
744
749
|
Data_Get_Struct(self, ossl_ec_group, ec_group);
|
745
750
|
if (ec_group->group != NULL)
|
746
|
-
|
751
|
+
ossl_raise(rb_eRuntimeError, "EC_GROUP is already initialized");
|
747
752
|
|
748
753
|
switch (rb_scan_args(argc, argv, "13", &arg1, &arg2, &arg3, &arg4)) {
|
749
754
|
case 1:
|
@@ -765,7 +770,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
|
|
765
770
|
if ((group = EC_GROUP_new(method)) == NULL)
|
766
771
|
ossl_raise(eEC_GROUP, "EC_GROUP_new");
|
767
772
|
} else {
|
768
|
-
|
773
|
+
ossl_raise(rb_eArgError, "unknown symbol, must be :GFp_simple, :GFp_mont, :GFp_nist or :GF2m_simple");
|
769
774
|
}
|
770
775
|
} else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
|
771
776
|
const EC_GROUP *arg1_group;
|
@@ -778,16 +783,17 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
|
|
778
783
|
|
779
784
|
group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
|
780
785
|
if (!group) {
|
781
|
-
|
786
|
+
OSSL_BIO_reset(in);
|
782
787
|
group = d2i_ECPKParameters_bio(in, NULL);
|
783
788
|
}
|
784
789
|
|
785
790
|
BIO_free(in);
|
786
791
|
|
787
792
|
if (!group) {
|
788
|
-
const char *name =
|
793
|
+
const char *name = StringValueCStr(arg1);
|
789
794
|
int nid = OBJ_sn2nid(name);
|
790
795
|
|
796
|
+
(void)ERR_get_error();
|
791
797
|
if (nid == NID_undef)
|
792
798
|
ossl_raise(eEC_GROUP, "unknown curve name (%s)", name);
|
793
799
|
|
@@ -814,18 +820,18 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
|
|
814
820
|
} else if (id == s_GF2m) {
|
815
821
|
new_curve = EC_GROUP_new_curve_GF2m;
|
816
822
|
} else {
|
817
|
-
|
823
|
+
ossl_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m");
|
818
824
|
}
|
819
825
|
|
820
826
|
if ((group = new_curve(p, a, b, ossl_bn_ctx)) == NULL)
|
821
827
|
ossl_raise(eEC_GROUP, "EC_GROUP_new_by_GF*");
|
822
828
|
} else {
|
823
|
-
|
829
|
+
ossl_raise(rb_eArgError, "unknown argument, must be :GFp or :GF2m");
|
824
830
|
}
|
825
831
|
|
826
832
|
break;
|
827
833
|
default:
|
828
|
-
|
834
|
+
ossl_raise(rb_eArgError, "wrong number of arguments");
|
829
835
|
}
|
830
836
|
|
831
837
|
if (group == NULL)
|
@@ -965,7 +971,7 @@ static VALUE ossl_s_builtin_curves(VALUE self)
|
|
965
971
|
{
|
966
972
|
EC_builtin_curve *curves = NULL;
|
967
973
|
int n;
|
968
|
-
int crv_len = EC_get_builtin_curves(NULL, 0);
|
974
|
+
int crv_len = rb_long2int(EC_get_builtin_curves(NULL, 0));
|
969
975
|
VALUE ary, ret;
|
970
976
|
|
971
977
|
curves = ALLOCA_N(EC_builtin_curve, crv_len);
|
@@ -1023,7 +1029,7 @@ static VALUE ossl_ec_group_set_asn1_flag(VALUE self, VALUE flag_v)
|
|
1023
1029
|
}
|
1024
1030
|
|
1025
1031
|
/* call-seq:
|
1026
|
-
* group.point_conversion_form => :uncompressed | :compressed | :hybrid
|
1032
|
+
* group.point_conversion_form => :uncompressed | :compressed | :hybrid
|
1027
1033
|
*
|
1028
1034
|
* See the OpenSSL documentation for EC_GROUP_get_point_conversion_form()
|
1029
1035
|
*/
|
@@ -1041,9 +1047,9 @@ static VALUE ossl_ec_group_get_point_conversion_form(VALUE self)
|
|
1041
1047
|
case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed; break;
|
1042
1048
|
case POINT_CONVERSION_COMPRESSED: ret = ID_compressed; break;
|
1043
1049
|
case POINT_CONVERSION_HYBRID: ret = ID_hybrid; break;
|
1044
|
-
default:
|
1050
|
+
default: ossl_raise(eEC_GROUP, "unsupported point conversion form: %d, this module should be updated", form);
|
1045
1051
|
}
|
1046
|
-
|
1052
|
+
|
1047
1053
|
return ID2SYM(ret);
|
1048
1054
|
}
|
1049
1055
|
|
@@ -1067,7 +1073,7 @@ static VALUE ossl_ec_group_set_point_conversion_form(VALUE self, VALUE form_v)
|
|
1067
1073
|
} else if (form_id == ID_hybrid) {
|
1068
1074
|
form = POINT_CONVERSION_HYBRID;
|
1069
1075
|
} else {
|
1070
|
-
|
1076
|
+
ossl_raise(rb_eArgError, "form must be :compressed, :uncompressed, or :hybrid");
|
1071
1077
|
}
|
1072
1078
|
|
1073
1079
|
EC_GROUP_set_point_conversion_form(group, form);
|
@@ -1092,7 +1098,7 @@ static VALUE ossl_ec_group_get_seed(VALUE self)
|
|
1092
1098
|
if (seed_len == 0)
|
1093
1099
|
return Qnil;
|
1094
1100
|
|
1095
|
-
return rb_str_new(EC_GROUP_get0_seed(group), seed_len);
|
1101
|
+
return rb_str_new((const char *)EC_GROUP_get0_seed(group), seed_len);
|
1096
1102
|
}
|
1097
1103
|
|
1098
1104
|
/* call-seq:
|
@@ -1107,7 +1113,7 @@ static VALUE ossl_ec_group_set_seed(VALUE self, VALUE seed)
|
|
1107
1113
|
Require_EC_GROUP(self, group);
|
1108
1114
|
StringValue(seed);
|
1109
1115
|
|
1110
|
-
if (EC_GROUP_set_seed(group, RSTRING_PTR(seed), RSTRING_LEN(seed)) != RSTRING_LEN(seed))
|
1116
|
+
if (EC_GROUP_set_seed(group, (unsigned char *)RSTRING_PTR(seed), RSTRING_LEN(seed)) != (size_t)RSTRING_LEN(seed))
|
1111
1117
|
ossl_raise(eEC_GROUP, "EC_GROUP_set_seed");
|
1112
1118
|
|
1113
1119
|
return seed;
|
@@ -1150,7 +1156,7 @@ static VALUE ossl_ec_group_to_string(VALUE self, int format)
|
|
1150
1156
|
break;
|
1151
1157
|
default:
|
1152
1158
|
BIO_free(out);
|
1153
|
-
|
1159
|
+
ossl_raise(rb_eRuntimeError, "unknown format (internal error)");
|
1154
1160
|
}
|
1155
1161
|
|
1156
1162
|
if (i != 1) {
|
@@ -1243,7 +1249,7 @@ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
|
|
1243
1249
|
|
1244
1250
|
Data_Get_Struct(self, ossl_ec_point, ec_point);
|
1245
1251
|
if (ec_point->point)
|
1246
|
-
|
1252
|
+
ossl_raise(eEC_POINT, "EC_POINT already initialized");
|
1247
1253
|
|
1248
1254
|
switch (rb_scan_args(argc, argv, "11", &arg1, &arg2)) {
|
1249
1255
|
case 1:
|
@@ -1261,16 +1267,16 @@ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
|
|
1261
1267
|
|
1262
1268
|
point = EC_POINT_new(group);
|
1263
1269
|
} else {
|
1264
|
-
|
1270
|
+
ossl_raise(eEC_POINT, "wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
|
1265
1271
|
}
|
1266
1272
|
|
1267
1273
|
break;
|
1268
1274
|
case 2:
|
1269
1275
|
if (!rb_obj_is_kind_of(arg1, cEC_GROUP))
|
1270
|
-
|
1276
|
+
ossl_raise(rb_eArgError, "1st argument must be OpenSSL::PKey::EC::Group");
|
1271
1277
|
group_v = arg1;
|
1272
1278
|
SafeRequire_EC_GROUP(group_v, group);
|
1273
|
-
|
1279
|
+
|
1274
1280
|
if (rb_obj_is_kind_of(arg2, cBN)) {
|
1275
1281
|
const BIGNUM *bn = GetBNPtr(arg2);
|
1276
1282
|
|
@@ -1288,14 +1294,14 @@ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
|
|
1288
1294
|
}
|
1289
1295
|
break;
|
1290
1296
|
default:
|
1291
|
-
|
1297
|
+
ossl_raise(rb_eArgError, "wrong number of arguments");
|
1292
1298
|
}
|
1293
1299
|
|
1294
1300
|
if (point == NULL)
|
1295
1301
|
ossl_raise(eEC_POINT, NULL);
|
1296
1302
|
|
1297
1303
|
if (NIL_P(group_v))
|
1298
|
-
|
1304
|
+
ossl_raise(rb_eRuntimeError, "missing group (internal error)");
|
1299
1305
|
|
1300
1306
|
ec_point->point = point;
|
1301
1307
|
|
@@ -1348,6 +1354,8 @@ static VALUE ossl_ec_point_is_at_infinity(VALUE self)
|
|
1348
1354
|
case 0: return Qfalse;
|
1349
1355
|
default: ossl_raise(cEC_POINT, "EC_POINT_is_at_infinity");
|
1350
1356
|
}
|
1357
|
+
|
1358
|
+
UNREACHABLE;
|
1351
1359
|
}
|
1352
1360
|
|
1353
1361
|
/*
|
@@ -1369,6 +1377,8 @@ static VALUE ossl_ec_point_is_on_curve(VALUE self)
|
|
1369
1377
|
case 0: return Qfalse;
|
1370
1378
|
default: ossl_raise(cEC_POINT, "EC_POINT_is_on_curve");
|
1371
1379
|
}
|
1380
|
+
|
1381
|
+
UNREACHABLE;
|
1372
1382
|
}
|
1373
1383
|
|
1374
1384
|
/*
|
@@ -1460,6 +1470,78 @@ static VALUE ossl_ec_point_to_bn(VALUE self)
|
|
1460
1470
|
return bn_obj;
|
1461
1471
|
}
|
1462
1472
|
|
1473
|
+
/*
|
1474
|
+
* call-seq:
|
1475
|
+
* point.mul(bn) => point
|
1476
|
+
* point.mul(bn, bn) => point
|
1477
|
+
* point.mul([bn], [point]) => point
|
1478
|
+
* point.mul([bn], [point], bn) => point
|
1479
|
+
*/
|
1480
|
+
static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
|
1481
|
+
{
|
1482
|
+
EC_POINT *point1, *point2;
|
1483
|
+
const EC_GROUP *group;
|
1484
|
+
VALUE group_v = rb_iv_get(self, "@group");
|
1485
|
+
VALUE bn_v1, bn_v2, r, points_v;
|
1486
|
+
BIGNUM *bn1 = NULL, *bn2 = NULL;
|
1487
|
+
|
1488
|
+
Require_EC_POINT(self, point1);
|
1489
|
+
SafeRequire_EC_GROUP(group_v, group);
|
1490
|
+
|
1491
|
+
r = rb_obj_alloc(cEC_POINT);
|
1492
|
+
ossl_ec_point_initialize(1, &group_v, r);
|
1493
|
+
Require_EC_POINT(r, point2);
|
1494
|
+
|
1495
|
+
argc = rb_scan_args(argc, argv, "12", &bn_v1, &points_v, &bn_v2);
|
1496
|
+
|
1497
|
+
if (rb_obj_is_kind_of(bn_v1, cBN)) {
|
1498
|
+
bn1 = GetBNPtr(bn_v1);
|
1499
|
+
if (argc >= 2) {
|
1500
|
+
bn2 = GetBNPtr(points_v);
|
1501
|
+
}
|
1502
|
+
if (EC_POINT_mul(group, point2, bn2, point1, bn1, ossl_bn_ctx) != 1)
|
1503
|
+
ossl_raise(eEC_POINT, "Multiplication failed");
|
1504
|
+
} else {
|
1505
|
+
size_t i, points_len, bignums_len;
|
1506
|
+
const EC_POINT **points;
|
1507
|
+
const BIGNUM **bignums;
|
1508
|
+
|
1509
|
+
Check_Type(bn_v1, T_ARRAY);
|
1510
|
+
bignums_len = RARRAY_LEN(bn_v1);
|
1511
|
+
bignums = (const BIGNUM **)OPENSSL_malloc(bignums_len * (int)sizeof(BIGNUM *));
|
1512
|
+
|
1513
|
+
for (i = 0; i < bignums_len; ++i) {
|
1514
|
+
bignums[i] = GetBNPtr(rb_ary_entry(bn_v1, i));
|
1515
|
+
}
|
1516
|
+
|
1517
|
+
if (!rb_obj_is_kind_of(points_v, rb_cArray)) {
|
1518
|
+
OPENSSL_free((void *)bignums);
|
1519
|
+
rb_raise(rb_eTypeError, "Argument2 must be an array");
|
1520
|
+
}
|
1521
|
+
|
1522
|
+
rb_ary_unshift(points_v, self);
|
1523
|
+
points_len = RARRAY_LEN(points_v);
|
1524
|
+
points = (const EC_POINT **)OPENSSL_malloc(points_len * (int)sizeof(EC_POINT *));
|
1525
|
+
|
1526
|
+
for (i = 0; i < points_len; ++i) {
|
1527
|
+
Get_EC_POINT(rb_ary_entry(points_v, i), points[i]);
|
1528
|
+
}
|
1529
|
+
|
1530
|
+
if (argc >= 3) {
|
1531
|
+
bn2 = GetBNPtr(bn_v2);
|
1532
|
+
}
|
1533
|
+
if (EC_POINTs_mul(group, point2, bn2, points_len, points, bignums, ossl_bn_ctx) != 1) {
|
1534
|
+
OPENSSL_free((void *)bignums);
|
1535
|
+
OPENSSL_free((void *)points);
|
1536
|
+
ossl_raise(eEC_POINT, "Multiplication failed");
|
1537
|
+
}
|
1538
|
+
OPENSSL_free((void *)bignums);
|
1539
|
+
OPENSSL_free((void *)points);
|
1540
|
+
}
|
1541
|
+
|
1542
|
+
return r;
|
1543
|
+
}
|
1544
|
+
|
1463
1545
|
static void no_copy(VALUE klass)
|
1464
1546
|
{
|
1465
1547
|
rb_undef_method(klass, "copy");
|
@@ -1526,7 +1608,8 @@ void Init_ossl_ec()
|
|
1526
1608
|
rb_define_method(cEC, "dsa_verify_asn1", ossl_ec_key_dsa_verify_asn1, 2);
|
1527
1609
|
/* do_sign/do_verify */
|
1528
1610
|
|
1529
|
-
rb_define_method(cEC, "
|
1611
|
+
rb_define_method(cEC, "export", ossl_ec_key_export, -1);
|
1612
|
+
rb_define_alias(cEC, "to_pem", "export");
|
1530
1613
|
rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0);
|
1531
1614
|
rb_define_method(cEC, "to_text", ossl_ec_key_to_text, 0);
|
1532
1615
|
|
@@ -1580,6 +1663,7 @@ void Init_ossl_ec()
|
|
1580
1663
|
/* all the other methods */
|
1581
1664
|
|
1582
1665
|
rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, 0);
|
1666
|
+
rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1);
|
1583
1667
|
|
1584
1668
|
no_copy(cEC);
|
1585
1669
|
no_copy(cEC_GROUP);
|