openssl 2.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of openssl might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/BSDL +22 -0
- data/CONTRIBUTING.md +130 -0
- data/History.md +118 -0
- data/LICENSE.txt +56 -0
- data/README.md +70 -0
- data/ext/openssl/deprecation.rb +26 -0
- data/ext/openssl/extconf.rb +158 -0
- data/ext/openssl/openssl_missing.c +173 -0
- data/ext/openssl/openssl_missing.h +244 -0
- data/ext/openssl/ossl.c +1201 -0
- data/ext/openssl/ossl.h +222 -0
- data/ext/openssl/ossl_asn1.c +1992 -0
- data/ext/openssl/ossl_asn1.h +66 -0
- data/ext/openssl/ossl_bio.c +87 -0
- data/ext/openssl/ossl_bio.h +19 -0
- data/ext/openssl/ossl_bn.c +1153 -0
- data/ext/openssl/ossl_bn.h +23 -0
- data/ext/openssl/ossl_cipher.c +1085 -0
- data/ext/openssl/ossl_cipher.h +20 -0
- data/ext/openssl/ossl_config.c +89 -0
- data/ext/openssl/ossl_config.h +19 -0
- data/ext/openssl/ossl_digest.c +453 -0
- data/ext/openssl/ossl_digest.h +20 -0
- data/ext/openssl/ossl_engine.c +580 -0
- data/ext/openssl/ossl_engine.h +19 -0
- data/ext/openssl/ossl_hmac.c +398 -0
- data/ext/openssl/ossl_hmac.h +18 -0
- data/ext/openssl/ossl_ns_spki.c +406 -0
- data/ext/openssl/ossl_ns_spki.h +19 -0
- data/ext/openssl/ossl_ocsp.c +2013 -0
- data/ext/openssl/ossl_ocsp.h +23 -0
- data/ext/openssl/ossl_pkcs12.c +259 -0
- data/ext/openssl/ossl_pkcs12.h +13 -0
- data/ext/openssl/ossl_pkcs5.c +180 -0
- data/ext/openssl/ossl_pkcs5.h +6 -0
- data/ext/openssl/ossl_pkcs7.c +1125 -0
- data/ext/openssl/ossl_pkcs7.h +20 -0
- data/ext/openssl/ossl_pkey.c +435 -0
- data/ext/openssl/ossl_pkey.h +245 -0
- data/ext/openssl/ossl_pkey_dh.c +650 -0
- data/ext/openssl/ossl_pkey_dsa.c +672 -0
- data/ext/openssl/ossl_pkey_ec.c +1899 -0
- data/ext/openssl/ossl_pkey_rsa.c +768 -0
- data/ext/openssl/ossl_rand.c +238 -0
- data/ext/openssl/ossl_rand.h +18 -0
- data/ext/openssl/ossl_ssl.c +2679 -0
- data/ext/openssl/ossl_ssl.h +41 -0
- data/ext/openssl/ossl_ssl_session.c +352 -0
- data/ext/openssl/ossl_version.h +15 -0
- data/ext/openssl/ossl_x509.c +186 -0
- data/ext/openssl/ossl_x509.h +119 -0
- data/ext/openssl/ossl_x509attr.c +328 -0
- data/ext/openssl/ossl_x509cert.c +860 -0
- data/ext/openssl/ossl_x509crl.c +565 -0
- data/ext/openssl/ossl_x509ext.c +480 -0
- data/ext/openssl/ossl_x509name.c +547 -0
- data/ext/openssl/ossl_x509req.c +492 -0
- data/ext/openssl/ossl_x509revoked.c +279 -0
- data/ext/openssl/ossl_x509store.c +846 -0
- data/ext/openssl/ruby_missing.h +32 -0
- data/lib/openssl.rb +21 -0
- data/lib/openssl/bn.rb +39 -0
- data/lib/openssl/buffering.rb +451 -0
- data/lib/openssl/cipher.rb +67 -0
- data/lib/openssl/config.rb +473 -0
- data/lib/openssl/digest.rb +78 -0
- data/lib/openssl/pkey.rb +44 -0
- data/lib/openssl/ssl.rb +416 -0
- data/lib/openssl/x509.rb +176 -0
- metadata +178 -0
@@ -0,0 +1,672 @@
|
|
1
|
+
/*
|
2
|
+
* 'OpenSSL for Ruby' project
|
3
|
+
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
4
|
+
* All rights reserved.
|
5
|
+
*/
|
6
|
+
/*
|
7
|
+
* This program is licensed under the same licence as Ruby.
|
8
|
+
* (See the file 'LICENCE'.)
|
9
|
+
*/
|
10
|
+
#include "ossl.h"
|
11
|
+
|
12
|
+
#if !defined(OPENSSL_NO_DSA)
|
13
|
+
|
14
|
+
#define GetPKeyDSA(obj, pkey) do { \
|
15
|
+
GetPKey((obj), (pkey)); \
|
16
|
+
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DSA) { /* PARANOIA? */ \
|
17
|
+
ossl_raise(rb_eRuntimeError, "THIS IS NOT A DSA!"); \
|
18
|
+
} \
|
19
|
+
} while (0)
|
20
|
+
#define GetDSA(obj, dsa) do { \
|
21
|
+
EVP_PKEY *_pkey; \
|
22
|
+
GetPKeyDSA((obj), _pkey); \
|
23
|
+
(dsa) = EVP_PKEY_get0_DSA(_pkey); \
|
24
|
+
} while (0)
|
25
|
+
|
26
|
+
static inline int
|
27
|
+
DSA_HAS_PRIVATE(DSA *dsa)
|
28
|
+
{
|
29
|
+
const BIGNUM *bn;
|
30
|
+
DSA_get0_key(dsa, NULL, &bn);
|
31
|
+
return !!bn;
|
32
|
+
}
|
33
|
+
|
34
|
+
static inline int
|
35
|
+
DSA_PRIVATE(VALUE obj, DSA *dsa)
|
36
|
+
{
|
37
|
+
return DSA_HAS_PRIVATE(dsa) || OSSL_PKEY_IS_PRIVATE(obj);
|
38
|
+
}
|
39
|
+
|
40
|
+
/*
|
41
|
+
* Classes
|
42
|
+
*/
|
43
|
+
VALUE cDSA;
|
44
|
+
VALUE eDSAError;
|
45
|
+
|
46
|
+
/*
|
47
|
+
* Public
|
48
|
+
*/
|
49
|
+
static VALUE
|
50
|
+
dsa_instance(VALUE klass, DSA *dsa)
|
51
|
+
{
|
52
|
+
EVP_PKEY *pkey;
|
53
|
+
VALUE obj;
|
54
|
+
|
55
|
+
if (!dsa) {
|
56
|
+
return Qfalse;
|
57
|
+
}
|
58
|
+
obj = NewPKey(klass);
|
59
|
+
if (!(pkey = EVP_PKEY_new())) {
|
60
|
+
return Qfalse;
|
61
|
+
}
|
62
|
+
if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
|
63
|
+
EVP_PKEY_free(pkey);
|
64
|
+
return Qfalse;
|
65
|
+
}
|
66
|
+
SetPKey(obj, pkey);
|
67
|
+
|
68
|
+
return obj;
|
69
|
+
}
|
70
|
+
|
71
|
+
VALUE
|
72
|
+
ossl_dsa_new(EVP_PKEY *pkey)
|
73
|
+
{
|
74
|
+
VALUE obj;
|
75
|
+
|
76
|
+
if (!pkey) {
|
77
|
+
obj = dsa_instance(cDSA, DSA_new());
|
78
|
+
} else {
|
79
|
+
obj = NewPKey(cDSA);
|
80
|
+
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DSA) {
|
81
|
+
ossl_raise(rb_eTypeError, "Not a DSA key!");
|
82
|
+
}
|
83
|
+
SetPKey(obj, pkey);
|
84
|
+
}
|
85
|
+
if (obj == Qfalse) {
|
86
|
+
ossl_raise(eDSAError, NULL);
|
87
|
+
}
|
88
|
+
|
89
|
+
return obj;
|
90
|
+
}
|
91
|
+
|
92
|
+
/*
|
93
|
+
* Private
|
94
|
+
*/
|
95
|
+
struct dsa_blocking_gen_arg {
|
96
|
+
DSA *dsa;
|
97
|
+
int size;
|
98
|
+
int *counter;
|
99
|
+
unsigned long *h;
|
100
|
+
BN_GENCB *cb;
|
101
|
+
int result;
|
102
|
+
};
|
103
|
+
|
104
|
+
static void *
|
105
|
+
dsa_blocking_gen(void *arg)
|
106
|
+
{
|
107
|
+
struct dsa_blocking_gen_arg *gen = (struct dsa_blocking_gen_arg *)arg;
|
108
|
+
gen->result = DSA_generate_parameters_ex(gen->dsa, gen->size, NULL, 0,
|
109
|
+
gen->counter, gen->h, gen->cb);
|
110
|
+
return 0;
|
111
|
+
}
|
112
|
+
|
113
|
+
static DSA *
|
114
|
+
dsa_generate(int size)
|
115
|
+
{
|
116
|
+
struct ossl_generate_cb_arg cb_arg = { 0 };
|
117
|
+
struct dsa_blocking_gen_arg gen_arg;
|
118
|
+
DSA *dsa = DSA_new();
|
119
|
+
BN_GENCB *cb = BN_GENCB_new();
|
120
|
+
int counter;
|
121
|
+
unsigned long h;
|
122
|
+
|
123
|
+
if (!dsa || !cb) {
|
124
|
+
DSA_free(dsa);
|
125
|
+
BN_GENCB_free(cb);
|
126
|
+
return NULL;
|
127
|
+
}
|
128
|
+
|
129
|
+
if (rb_block_given_p())
|
130
|
+
cb_arg.yield = 1;
|
131
|
+
BN_GENCB_set(cb, ossl_generate_cb_2, &cb_arg);
|
132
|
+
gen_arg.dsa = dsa;
|
133
|
+
gen_arg.size = size;
|
134
|
+
gen_arg.counter = &counter;
|
135
|
+
gen_arg.h = &h;
|
136
|
+
gen_arg.cb = cb;
|
137
|
+
if (cb_arg.yield == 1) {
|
138
|
+
/* we cannot release GVL when callback proc is supplied */
|
139
|
+
dsa_blocking_gen(&gen_arg);
|
140
|
+
} else {
|
141
|
+
/* there's a chance to unblock */
|
142
|
+
rb_thread_call_without_gvl(dsa_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg);
|
143
|
+
}
|
144
|
+
|
145
|
+
BN_GENCB_free(cb);
|
146
|
+
if (!gen_arg.result) {
|
147
|
+
DSA_free(dsa);
|
148
|
+
if (cb_arg.state) {
|
149
|
+
/* Clear OpenSSL error queue before re-raising. By the way, the
|
150
|
+
* documentation of DSA_generate_parameters_ex() says the error code
|
151
|
+
* can be obtained by ERR_get_error(), but the default
|
152
|
+
* implementation, dsa_builtin_paramgen() doesn't put any error... */
|
153
|
+
ossl_clear_error();
|
154
|
+
rb_jump_tag(cb_arg.state);
|
155
|
+
}
|
156
|
+
return NULL;
|
157
|
+
}
|
158
|
+
|
159
|
+
if (!DSA_generate_key(dsa)) {
|
160
|
+
DSA_free(dsa);
|
161
|
+
return NULL;
|
162
|
+
}
|
163
|
+
|
164
|
+
return dsa;
|
165
|
+
}
|
166
|
+
|
167
|
+
/*
|
168
|
+
* call-seq:
|
169
|
+
* DSA.generate(size) -> dsa
|
170
|
+
*
|
171
|
+
* Creates a new DSA instance by generating a private/public key pair
|
172
|
+
* from scratch.
|
173
|
+
*
|
174
|
+
* === Parameters
|
175
|
+
* * +size+ is an integer representing the desired key size.
|
176
|
+
*
|
177
|
+
*/
|
178
|
+
static VALUE
|
179
|
+
ossl_dsa_s_generate(VALUE klass, VALUE size)
|
180
|
+
{
|
181
|
+
DSA *dsa = dsa_generate(NUM2INT(size)); /* err handled by dsa_instance */
|
182
|
+
VALUE obj = dsa_instance(klass, dsa);
|
183
|
+
|
184
|
+
if (obj == Qfalse) {
|
185
|
+
DSA_free(dsa);
|
186
|
+
ossl_raise(eDSAError, NULL);
|
187
|
+
}
|
188
|
+
|
189
|
+
return obj;
|
190
|
+
}
|
191
|
+
|
192
|
+
/*
|
193
|
+
* call-seq:
|
194
|
+
* DSA.new -> dsa
|
195
|
+
* DSA.new(size) -> dsa
|
196
|
+
* DSA.new(string [, pass]) -> dsa
|
197
|
+
*
|
198
|
+
* Creates a new DSA instance by reading an existing key from +string+.
|
199
|
+
*
|
200
|
+
* === Parameters
|
201
|
+
* * +size+ is an integer representing the desired key size.
|
202
|
+
* * +string+ contains a DER or PEM encoded key.
|
203
|
+
* * +pass+ is a string that contains an optional password.
|
204
|
+
*
|
205
|
+
* === Examples
|
206
|
+
* DSA.new -> dsa
|
207
|
+
* DSA.new(1024) -> dsa
|
208
|
+
* DSA.new(File.read('dsa.pem')) -> dsa
|
209
|
+
* DSA.new(File.read('dsa.pem'), 'mypassword') -> dsa
|
210
|
+
*
|
211
|
+
*/
|
212
|
+
static VALUE
|
213
|
+
ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
|
214
|
+
{
|
215
|
+
EVP_PKEY *pkey;
|
216
|
+
DSA *dsa;
|
217
|
+
BIO *in;
|
218
|
+
VALUE arg, pass;
|
219
|
+
|
220
|
+
GetPKey(self, pkey);
|
221
|
+
if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
|
222
|
+
dsa = DSA_new();
|
223
|
+
}
|
224
|
+
else if (RB_INTEGER_TYPE_P(arg)) {
|
225
|
+
if (!(dsa = dsa_generate(NUM2INT(arg)))) {
|
226
|
+
ossl_raise(eDSAError, NULL);
|
227
|
+
}
|
228
|
+
}
|
229
|
+
else {
|
230
|
+
pass = ossl_pem_passwd_value(pass);
|
231
|
+
arg = ossl_to_der_if_possible(arg);
|
232
|
+
in = ossl_obj2bio(arg);
|
233
|
+
dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass);
|
234
|
+
if (!dsa) {
|
235
|
+
OSSL_BIO_reset(in);
|
236
|
+
dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL);
|
237
|
+
}
|
238
|
+
if (!dsa) {
|
239
|
+
OSSL_BIO_reset(in);
|
240
|
+
dsa = d2i_DSAPrivateKey_bio(in, NULL);
|
241
|
+
}
|
242
|
+
if (!dsa) {
|
243
|
+
OSSL_BIO_reset(in);
|
244
|
+
dsa = d2i_DSA_PUBKEY_bio(in, NULL);
|
245
|
+
}
|
246
|
+
if (!dsa) {
|
247
|
+
OSSL_BIO_reset(in);
|
248
|
+
#define PEM_read_bio_DSAPublicKey(bp,x,cb,u) (DSA *)PEM_ASN1_read_bio( \
|
249
|
+
(d2i_of_void *)d2i_DSAPublicKey, PEM_STRING_DSA_PUBLIC, (bp), (void **)(x), (cb), (u))
|
250
|
+
dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL);
|
251
|
+
#undef PEM_read_bio_DSAPublicKey
|
252
|
+
}
|
253
|
+
BIO_free(in);
|
254
|
+
if (!dsa) {
|
255
|
+
ossl_clear_error();
|
256
|
+
ossl_raise(eDSAError, "Neither PUB key nor PRIV key");
|
257
|
+
}
|
258
|
+
}
|
259
|
+
if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
|
260
|
+
DSA_free(dsa);
|
261
|
+
ossl_raise(eDSAError, NULL);
|
262
|
+
}
|
263
|
+
|
264
|
+
return self;
|
265
|
+
}
|
266
|
+
|
267
|
+
static VALUE
|
268
|
+
ossl_dsa_initialize_copy(VALUE self, VALUE other)
|
269
|
+
{
|
270
|
+
EVP_PKEY *pkey;
|
271
|
+
DSA *dsa, *dsa_new;
|
272
|
+
|
273
|
+
GetPKey(self, pkey);
|
274
|
+
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
|
275
|
+
ossl_raise(eDSAError, "DSA already initialized");
|
276
|
+
GetDSA(other, dsa);
|
277
|
+
|
278
|
+
dsa_new = ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey, (d2i_of_void *)d2i_DSAPrivateKey, (char *)dsa);
|
279
|
+
if (!dsa_new)
|
280
|
+
ossl_raise(eDSAError, "ASN1_dup");
|
281
|
+
|
282
|
+
EVP_PKEY_assign_DSA(pkey, dsa_new);
|
283
|
+
|
284
|
+
return self;
|
285
|
+
}
|
286
|
+
|
287
|
+
/*
|
288
|
+
* call-seq:
|
289
|
+
* dsa.public? -> true | false
|
290
|
+
*
|
291
|
+
* Indicates whether this DSA instance has a public key associated with it or
|
292
|
+
* not. The public key may be retrieved with DSA#public_key.
|
293
|
+
*/
|
294
|
+
static VALUE
|
295
|
+
ossl_dsa_is_public(VALUE self)
|
296
|
+
{
|
297
|
+
DSA *dsa;
|
298
|
+
const BIGNUM *bn;
|
299
|
+
|
300
|
+
GetDSA(self, dsa);
|
301
|
+
DSA_get0_key(dsa, &bn, NULL);
|
302
|
+
|
303
|
+
return bn ? Qtrue : Qfalse;
|
304
|
+
}
|
305
|
+
|
306
|
+
/*
|
307
|
+
* call-seq:
|
308
|
+
* dsa.private? -> true | false
|
309
|
+
*
|
310
|
+
* Indicates whether this DSA instance has a private key associated with it or
|
311
|
+
* not. The private key may be retrieved with DSA#private_key.
|
312
|
+
*/
|
313
|
+
static VALUE
|
314
|
+
ossl_dsa_is_private(VALUE self)
|
315
|
+
{
|
316
|
+
DSA *dsa;
|
317
|
+
|
318
|
+
GetDSA(self, dsa);
|
319
|
+
|
320
|
+
return DSA_PRIVATE(self, dsa) ? Qtrue : Qfalse;
|
321
|
+
}
|
322
|
+
|
323
|
+
/*
|
324
|
+
* call-seq:
|
325
|
+
* dsa.export([cipher, password]) -> aString
|
326
|
+
* dsa.to_pem([cipher, password]) -> aString
|
327
|
+
* dsa.to_s([cipher, password]) -> aString
|
328
|
+
*
|
329
|
+
* Encodes this DSA to its PEM encoding.
|
330
|
+
*
|
331
|
+
* === Parameters
|
332
|
+
* * +cipher+ is an OpenSSL::Cipher.
|
333
|
+
* * +password+ is a string containing your password.
|
334
|
+
*
|
335
|
+
* === Examples
|
336
|
+
* DSA.to_pem -> aString
|
337
|
+
* DSA.to_pem(cipher, 'mypassword') -> aString
|
338
|
+
*
|
339
|
+
*/
|
340
|
+
static VALUE
|
341
|
+
ossl_dsa_export(int argc, VALUE *argv, VALUE self)
|
342
|
+
{
|
343
|
+
DSA *dsa;
|
344
|
+
BIO *out;
|
345
|
+
const EVP_CIPHER *ciph = NULL;
|
346
|
+
VALUE cipher, pass, str;
|
347
|
+
|
348
|
+
GetDSA(self, dsa);
|
349
|
+
rb_scan_args(argc, argv, "02", &cipher, &pass);
|
350
|
+
if (!NIL_P(cipher)) {
|
351
|
+
ciph = GetCipherPtr(cipher);
|
352
|
+
pass = ossl_pem_passwd_value(pass);
|
353
|
+
}
|
354
|
+
if (!(out = BIO_new(BIO_s_mem()))) {
|
355
|
+
ossl_raise(eDSAError, NULL);
|
356
|
+
}
|
357
|
+
if (DSA_HAS_PRIVATE(dsa)) {
|
358
|
+
if (!PEM_write_bio_DSAPrivateKey(out, dsa, ciph, NULL, 0,
|
359
|
+
ossl_pem_passwd_cb, (void *)pass)){
|
360
|
+
BIO_free(out);
|
361
|
+
ossl_raise(eDSAError, NULL);
|
362
|
+
}
|
363
|
+
} else {
|
364
|
+
if (!PEM_write_bio_DSA_PUBKEY(out, dsa)) {
|
365
|
+
BIO_free(out);
|
366
|
+
ossl_raise(eDSAError, NULL);
|
367
|
+
}
|
368
|
+
}
|
369
|
+
str = ossl_membio2str(out);
|
370
|
+
|
371
|
+
return str;
|
372
|
+
}
|
373
|
+
|
374
|
+
/*
|
375
|
+
* call-seq:
|
376
|
+
* dsa.to_der -> aString
|
377
|
+
*
|
378
|
+
* Encodes this DSA to its DER encoding.
|
379
|
+
*
|
380
|
+
*/
|
381
|
+
static VALUE
|
382
|
+
ossl_dsa_to_der(VALUE self)
|
383
|
+
{
|
384
|
+
DSA *dsa;
|
385
|
+
int (*i2d_func)(DSA *, unsigned char **);
|
386
|
+
unsigned char *p;
|
387
|
+
long len;
|
388
|
+
VALUE str;
|
389
|
+
|
390
|
+
GetDSA(self, dsa);
|
391
|
+
if(DSA_HAS_PRIVATE(dsa))
|
392
|
+
i2d_func = (int (*)(DSA *,unsigned char **))i2d_DSAPrivateKey;
|
393
|
+
else
|
394
|
+
i2d_func = i2d_DSA_PUBKEY;
|
395
|
+
if((len = i2d_func(dsa, NULL)) <= 0)
|
396
|
+
ossl_raise(eDSAError, NULL);
|
397
|
+
str = rb_str_new(0, len);
|
398
|
+
p = (unsigned char *)RSTRING_PTR(str);
|
399
|
+
if(i2d_func(dsa, &p) < 0)
|
400
|
+
ossl_raise(eDSAError, NULL);
|
401
|
+
ossl_str_adjust(str, p);
|
402
|
+
|
403
|
+
return str;
|
404
|
+
}
|
405
|
+
|
406
|
+
|
407
|
+
/*
|
408
|
+
* call-seq:
|
409
|
+
* dsa.params -> hash
|
410
|
+
*
|
411
|
+
* Stores all parameters of key to the hash
|
412
|
+
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
|
413
|
+
* Don't use :-)) (I's up to you)
|
414
|
+
*/
|
415
|
+
static VALUE
|
416
|
+
ossl_dsa_get_params(VALUE self)
|
417
|
+
{
|
418
|
+
DSA *dsa;
|
419
|
+
VALUE hash;
|
420
|
+
const BIGNUM *p, *q, *g, *pub_key, *priv_key;
|
421
|
+
|
422
|
+
GetDSA(self, dsa);
|
423
|
+
DSA_get0_pqg(dsa, &p, &q, &g);
|
424
|
+
DSA_get0_key(dsa, &pub_key, &priv_key);
|
425
|
+
|
426
|
+
hash = rb_hash_new();
|
427
|
+
rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p));
|
428
|
+
rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q));
|
429
|
+
rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(g));
|
430
|
+
rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pub_key));
|
431
|
+
rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(priv_key));
|
432
|
+
|
433
|
+
return hash;
|
434
|
+
}
|
435
|
+
|
436
|
+
/*
|
437
|
+
* call-seq:
|
438
|
+
* dsa.to_text -> aString
|
439
|
+
*
|
440
|
+
* Prints all parameters of key to buffer
|
441
|
+
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
|
442
|
+
* Don't use :-)) (I's up to you)
|
443
|
+
*/
|
444
|
+
static VALUE
|
445
|
+
ossl_dsa_to_text(VALUE self)
|
446
|
+
{
|
447
|
+
DSA *dsa;
|
448
|
+
BIO *out;
|
449
|
+
VALUE str;
|
450
|
+
|
451
|
+
GetDSA(self, dsa);
|
452
|
+
if (!(out = BIO_new(BIO_s_mem()))) {
|
453
|
+
ossl_raise(eDSAError, NULL);
|
454
|
+
}
|
455
|
+
if (!DSA_print(out, dsa, 0)) { /* offset = 0 */
|
456
|
+
BIO_free(out);
|
457
|
+
ossl_raise(eDSAError, NULL);
|
458
|
+
}
|
459
|
+
str = ossl_membio2str(out);
|
460
|
+
|
461
|
+
return str;
|
462
|
+
}
|
463
|
+
|
464
|
+
/*
|
465
|
+
* call-seq:
|
466
|
+
* dsa.public_key -> aDSA
|
467
|
+
*
|
468
|
+
* Returns a new DSA instance that carries just the public key information.
|
469
|
+
* If the current instance has also private key information, this will no
|
470
|
+
* longer be present in the new instance. This feature is helpful for
|
471
|
+
* publishing the public key information without leaking any of the private
|
472
|
+
* information.
|
473
|
+
*
|
474
|
+
* === Example
|
475
|
+
* dsa = OpenSSL::PKey::DSA.new(2048) # has public and private information
|
476
|
+
* pub_key = dsa.public_key # has only the public part available
|
477
|
+
* pub_key_der = pub_key.to_der # it's safe to publish this
|
478
|
+
*
|
479
|
+
*
|
480
|
+
*/
|
481
|
+
static VALUE
|
482
|
+
ossl_dsa_to_public_key(VALUE self)
|
483
|
+
{
|
484
|
+
EVP_PKEY *pkey;
|
485
|
+
DSA *dsa;
|
486
|
+
VALUE obj;
|
487
|
+
|
488
|
+
GetPKeyDSA(self, pkey);
|
489
|
+
/* err check performed by dsa_instance */
|
490
|
+
#define DSAPublicKey_dup(dsa) (DSA *)ASN1_dup( \
|
491
|
+
(i2d_of_void *)i2d_DSAPublicKey, (d2i_of_void *)d2i_DSAPublicKey, (char *)(dsa))
|
492
|
+
dsa = DSAPublicKey_dup(EVP_PKEY_get0_DSA(pkey));
|
493
|
+
#undef DSAPublicKey_dup
|
494
|
+
obj = dsa_instance(CLASS_OF(self), dsa);
|
495
|
+
if (obj == Qfalse) {
|
496
|
+
DSA_free(dsa);
|
497
|
+
ossl_raise(eDSAError, NULL);
|
498
|
+
}
|
499
|
+
return obj;
|
500
|
+
}
|
501
|
+
|
502
|
+
#define ossl_dsa_buf_size(dsa) (DSA_size(dsa) + 16)
|
503
|
+
|
504
|
+
/*
|
505
|
+
* call-seq:
|
506
|
+
* dsa.syssign(string) -> aString
|
507
|
+
*
|
508
|
+
* Computes and returns the DSA signature of +string+, where +string+ is
|
509
|
+
* expected to be an already-computed message digest of the original input
|
510
|
+
* data. The signature is issued using the private key of this DSA instance.
|
511
|
+
*
|
512
|
+
* === Parameters
|
513
|
+
* * +string+ is a message digest of the original input data to be signed
|
514
|
+
*
|
515
|
+
* === Example
|
516
|
+
* dsa = OpenSSL::PKey::DSA.new(2048)
|
517
|
+
* doc = "Sign me"
|
518
|
+
* digest = OpenSSL::Digest::SHA1.digest(doc)
|
519
|
+
* sig = dsa.syssign(digest)
|
520
|
+
*
|
521
|
+
*
|
522
|
+
*/
|
523
|
+
static VALUE
|
524
|
+
ossl_dsa_sign(VALUE self, VALUE data)
|
525
|
+
{
|
526
|
+
DSA *dsa;
|
527
|
+
const BIGNUM *dsa_q;
|
528
|
+
unsigned int buf_len;
|
529
|
+
VALUE str;
|
530
|
+
|
531
|
+
GetDSA(self, dsa);
|
532
|
+
DSA_get0_pqg(dsa, NULL, &dsa_q, NULL);
|
533
|
+
if (!dsa_q)
|
534
|
+
ossl_raise(eDSAError, "incomplete DSA");
|
535
|
+
if (!DSA_PRIVATE(self, dsa))
|
536
|
+
ossl_raise(eDSAError, "Private DSA key needed!");
|
537
|
+
StringValue(data);
|
538
|
+
str = rb_str_new(0, ossl_dsa_buf_size(dsa));
|
539
|
+
if (!DSA_sign(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
|
540
|
+
(unsigned char *)RSTRING_PTR(str),
|
541
|
+
&buf_len, dsa)) { /* type is ignored (0) */
|
542
|
+
ossl_raise(eDSAError, NULL);
|
543
|
+
}
|
544
|
+
rb_str_set_len(str, buf_len);
|
545
|
+
|
546
|
+
return str;
|
547
|
+
}
|
548
|
+
|
549
|
+
/*
|
550
|
+
* call-seq:
|
551
|
+
* dsa.sysverify(digest, sig) -> true | false
|
552
|
+
*
|
553
|
+
* Verifies whether the signature is valid given the message digest input. It
|
554
|
+
* does so by validating +sig+ using the public key of this DSA instance.
|
555
|
+
*
|
556
|
+
* === Parameters
|
557
|
+
* * +digest+ is a message digest of the original input data to be signed
|
558
|
+
* * +sig+ is a DSA signature value
|
559
|
+
*
|
560
|
+
* === Example
|
561
|
+
* dsa = OpenSSL::PKey::DSA.new(2048)
|
562
|
+
* doc = "Sign me"
|
563
|
+
* digest = OpenSSL::Digest::SHA1.digest(doc)
|
564
|
+
* sig = dsa.syssign(digest)
|
565
|
+
* puts dsa.sysverify(digest, sig) # => true
|
566
|
+
*
|
567
|
+
*/
|
568
|
+
static VALUE
|
569
|
+
ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
|
570
|
+
{
|
571
|
+
DSA *dsa;
|
572
|
+
int ret;
|
573
|
+
|
574
|
+
GetDSA(self, dsa);
|
575
|
+
StringValue(digest);
|
576
|
+
StringValue(sig);
|
577
|
+
/* type is ignored (0) */
|
578
|
+
ret = DSA_verify(0, (unsigned char *)RSTRING_PTR(digest), RSTRING_LENINT(digest),
|
579
|
+
(unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), dsa);
|
580
|
+
if (ret < 0) {
|
581
|
+
ossl_raise(eDSAError, NULL);
|
582
|
+
}
|
583
|
+
else if (ret == 1) {
|
584
|
+
return Qtrue;
|
585
|
+
}
|
586
|
+
|
587
|
+
return Qfalse;
|
588
|
+
}
|
589
|
+
|
590
|
+
/*
|
591
|
+
* Document-method: OpenSSL::PKey::DSA#set_pqg
|
592
|
+
* call-seq:
|
593
|
+
* dsa.set_pqg(p, q, g) -> self
|
594
|
+
*
|
595
|
+
* Sets +p+, +q+, +g+ for the DSA instance.
|
596
|
+
*/
|
597
|
+
OSSL_PKEY_BN_DEF3(dsa, DSA, pqg, p, q, g)
|
598
|
+
/*
|
599
|
+
* Document-method: OpenSSL::PKey::DSA#set_key
|
600
|
+
* call-seq:
|
601
|
+
* dsa.set_key(pub_key, priv_key) -> self
|
602
|
+
*
|
603
|
+
* Sets +pub_key+ and +priv_key+ for the DSA instance. +priv_key+ may be nil.
|
604
|
+
*/
|
605
|
+
OSSL_PKEY_BN_DEF2(dsa, DSA, key, pub_key, priv_key)
|
606
|
+
|
607
|
+
/*
|
608
|
+
* INIT
|
609
|
+
*/
|
610
|
+
void
|
611
|
+
Init_ossl_dsa(void)
|
612
|
+
{
|
613
|
+
#if 0
|
614
|
+
mPKey = rb_define_module_under(mOSSL, "PKey");
|
615
|
+
cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
|
616
|
+
ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
|
617
|
+
#endif
|
618
|
+
|
619
|
+
/* Document-class: OpenSSL::PKey::DSAError
|
620
|
+
*
|
621
|
+
* Generic exception that is raised if an operation on a DSA PKey
|
622
|
+
* fails unexpectedly or in case an instantiation of an instance of DSA
|
623
|
+
* fails due to non-conformant input data.
|
624
|
+
*/
|
625
|
+
eDSAError = rb_define_class_under(mPKey, "DSAError", ePKeyError);
|
626
|
+
|
627
|
+
/* Document-class: OpenSSL::PKey::DSA
|
628
|
+
*
|
629
|
+
* DSA, the Digital Signature Algorithm, is specified in NIST's
|
630
|
+
* FIPS 186-3. It is an asymmetric public key algorithm that may be used
|
631
|
+
* similar to e.g. RSA.
|
632
|
+
* Please note that for OpenSSL versions prior to 1.0.0 the digest
|
633
|
+
* algorithms OpenSSL::Digest::DSS (equivalent to SHA) or
|
634
|
+
* OpenSSL::Digest::DSS1 (equivalent to SHA-1) must be used for issuing
|
635
|
+
* signatures with a DSA key using OpenSSL::PKey#sign.
|
636
|
+
* Starting with OpenSSL 1.0.0, digest algorithms are no longer restricted,
|
637
|
+
* any Digest may be used for signing.
|
638
|
+
*/
|
639
|
+
cDSA = rb_define_class_under(mPKey, "DSA", cPKey);
|
640
|
+
|
641
|
+
rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1);
|
642
|
+
rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1);
|
643
|
+
rb_define_copy_func(cDSA, ossl_dsa_initialize_copy);
|
644
|
+
|
645
|
+
rb_define_method(cDSA, "public?", ossl_dsa_is_public, 0);
|
646
|
+
rb_define_method(cDSA, "private?", ossl_dsa_is_private, 0);
|
647
|
+
rb_define_method(cDSA, "to_text", ossl_dsa_to_text, 0);
|
648
|
+
rb_define_method(cDSA, "export", ossl_dsa_export, -1);
|
649
|
+
rb_define_alias(cDSA, "to_pem", "export");
|
650
|
+
rb_define_alias(cDSA, "to_s", "export");
|
651
|
+
rb_define_method(cDSA, "to_der", ossl_dsa_to_der, 0);
|
652
|
+
rb_define_method(cDSA, "public_key", ossl_dsa_to_public_key, 0);
|
653
|
+
rb_define_method(cDSA, "syssign", ossl_dsa_sign, 1);
|
654
|
+
rb_define_method(cDSA, "sysverify", ossl_dsa_verify, 2);
|
655
|
+
|
656
|
+
DEF_OSSL_PKEY_BN(cDSA, dsa, p);
|
657
|
+
DEF_OSSL_PKEY_BN(cDSA, dsa, q);
|
658
|
+
DEF_OSSL_PKEY_BN(cDSA, dsa, g);
|
659
|
+
DEF_OSSL_PKEY_BN(cDSA, dsa, pub_key);
|
660
|
+
DEF_OSSL_PKEY_BN(cDSA, dsa, priv_key);
|
661
|
+
rb_define_method(cDSA, "set_pqg", ossl_dsa_set_pqg, 3);
|
662
|
+
rb_define_method(cDSA, "set_key", ossl_dsa_set_key, 2);
|
663
|
+
|
664
|
+
rb_define_method(cDSA, "params", ossl_dsa_get_params, 0);
|
665
|
+
}
|
666
|
+
|
667
|
+
#else /* defined NO_DSA */
|
668
|
+
void
|
669
|
+
Init_ossl_dsa(void)
|
670
|
+
{
|
671
|
+
}
|
672
|
+
#endif /* NO_DSA */
|