openssl-custom 2.2.2
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 +7 -0
- data/BSDL +22 -0
- data/CONTRIBUTING.md +132 -0
- data/History.md +485 -0
- data/LICENSE.txt +56 -0
- data/README.md +66 -0
- data/ext/openssl/extconf.rb +190 -0
- data/ext/openssl/openssl_missing.c +106 -0
- data/ext/openssl/openssl_missing.h +257 -0
- data/ext/openssl/ossl.c +1282 -0
- data/ext/openssl/ossl.h +181 -0
- data/ext/openssl/ossl_asn1.c +1878 -0
- data/ext/openssl/ossl_asn1.h +62 -0
- data/ext/openssl/ossl_bio.c +42 -0
- data/ext/openssl/ossl_bio.h +16 -0
- data/ext/openssl/ossl_bn.c +1270 -0
- data/ext/openssl/ossl_bn.h +26 -0
- data/ext/openssl/ossl_cipher.c +1075 -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 +425 -0
- data/ext/openssl/ossl_digest.h +20 -0
- data/ext/openssl/ossl_engine.c +567 -0
- data/ext/openssl/ossl_engine.h +19 -0
- data/ext/openssl/ossl_hmac.c +389 -0
- data/ext/openssl/ossl_hmac.h +18 -0
- data/ext/openssl/ossl_kdf.c +303 -0
- data/ext/openssl/ossl_kdf.h +6 -0
- data/ext/openssl/ossl_ns_spki.c +405 -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 +257 -0
- data/ext/openssl/ossl_pkcs12.h +13 -0
- data/ext/openssl/ossl_pkcs7.c +1098 -0
- data/ext/openssl/ossl_pkcs7.h +36 -0
- data/ext/openssl/ossl_pkey.c +673 -0
- data/ext/openssl/ossl_pkey.h +241 -0
- data/ext/openssl/ossl_pkey_dh.c +650 -0
- data/ext/openssl/ossl_pkey_dsa.c +664 -0
- data/ext/openssl/ossl_pkey_ec.c +1827 -0
- data/ext/openssl/ossl_pkey_rsa.c +966 -0
- data/ext/openssl/ossl_rand.c +200 -0
- data/ext/openssl/ossl_rand.h +18 -0
- data/ext/openssl/ossl_ssl.c +3080 -0
- data/ext/openssl/ossl_ssl.h +36 -0
- data/ext/openssl/ossl_ssl_session.c +332 -0
- data/ext/openssl/ossl_ts.c +1524 -0
- data/ext/openssl/ossl_ts.h +16 -0
- data/ext/openssl/ossl_x509.c +262 -0
- data/ext/openssl/ossl_x509.h +115 -0
- data/ext/openssl/ossl_x509attr.c +324 -0
- data/ext/openssl/ossl_x509cert.c +846 -0
- data/ext/openssl/ossl_x509crl.c +542 -0
- data/ext/openssl/ossl_x509ext.c +491 -0
- data/ext/openssl/ossl_x509name.c +590 -0
- data/ext/openssl/ossl_x509req.c +441 -0
- data/ext/openssl/ossl_x509revoked.c +300 -0
- data/ext/openssl/ossl_x509store.c +902 -0
- data/ext/openssl/ruby_missing.h +24 -0
- data/lib/openssl/bn.rb +40 -0
- data/lib/openssl/buffering.rb +478 -0
- data/lib/openssl/cipher.rb +67 -0
- data/lib/openssl/config.rb +501 -0
- data/lib/openssl/digest.rb +73 -0
- data/lib/openssl/hmac.rb +13 -0
- data/lib/openssl/marshal.rb +30 -0
- data/lib/openssl/pkcs5.rb +22 -0
- data/lib/openssl/pkey.rb +42 -0
- data/lib/openssl/ssl.rb +542 -0
- data/lib/openssl/version.rb +5 -0
- data/lib/openssl/x509.rb +369 -0
- data/lib/openssl.rb +38 -0
- metadata +196 -0
@@ -0,0 +1,650 @@
|
|
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_DH)
|
13
|
+
|
14
|
+
#define GetPKeyDH(obj, pkey) do { \
|
15
|
+
GetPKey((obj), (pkey)); \
|
16
|
+
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) { /* PARANOIA? */ \
|
17
|
+
ossl_raise(rb_eRuntimeError, "THIS IS NOT A DH!") ; \
|
18
|
+
} \
|
19
|
+
} while (0)
|
20
|
+
#define GetDH(obj, dh) do { \
|
21
|
+
EVP_PKEY *_pkey; \
|
22
|
+
GetPKeyDH((obj), _pkey); \
|
23
|
+
(dh) = EVP_PKEY_get0_DH(_pkey); \
|
24
|
+
} while (0)
|
25
|
+
|
26
|
+
/*
|
27
|
+
* Classes
|
28
|
+
*/
|
29
|
+
VALUE cDH;
|
30
|
+
VALUE eDHError;
|
31
|
+
|
32
|
+
/*
|
33
|
+
* Public
|
34
|
+
*/
|
35
|
+
static VALUE
|
36
|
+
dh_instance(VALUE klass, DH *dh)
|
37
|
+
{
|
38
|
+
EVP_PKEY *pkey;
|
39
|
+
VALUE obj;
|
40
|
+
|
41
|
+
if (!dh) {
|
42
|
+
return Qfalse;
|
43
|
+
}
|
44
|
+
obj = NewPKey(klass);
|
45
|
+
if (!(pkey = EVP_PKEY_new())) {
|
46
|
+
return Qfalse;
|
47
|
+
}
|
48
|
+
if (!EVP_PKEY_assign_DH(pkey, dh)) {
|
49
|
+
EVP_PKEY_free(pkey);
|
50
|
+
return Qfalse;
|
51
|
+
}
|
52
|
+
SetPKey(obj, pkey);
|
53
|
+
|
54
|
+
return obj;
|
55
|
+
}
|
56
|
+
|
57
|
+
VALUE
|
58
|
+
ossl_dh_new(EVP_PKEY *pkey)
|
59
|
+
{
|
60
|
+
VALUE obj;
|
61
|
+
|
62
|
+
if (!pkey) {
|
63
|
+
obj = dh_instance(cDH, DH_new());
|
64
|
+
} else {
|
65
|
+
obj = NewPKey(cDH);
|
66
|
+
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) {
|
67
|
+
ossl_raise(rb_eTypeError, "Not a DH key!");
|
68
|
+
}
|
69
|
+
SetPKey(obj, pkey);
|
70
|
+
}
|
71
|
+
if (obj == Qfalse) {
|
72
|
+
ossl_raise(eDHError, NULL);
|
73
|
+
}
|
74
|
+
|
75
|
+
return obj;
|
76
|
+
}
|
77
|
+
|
78
|
+
/*
|
79
|
+
* Private
|
80
|
+
*/
|
81
|
+
struct dh_blocking_gen_arg {
|
82
|
+
DH *dh;
|
83
|
+
int size;
|
84
|
+
int gen;
|
85
|
+
BN_GENCB *cb;
|
86
|
+
int result;
|
87
|
+
};
|
88
|
+
|
89
|
+
static void *
|
90
|
+
dh_blocking_gen(void *arg)
|
91
|
+
{
|
92
|
+
struct dh_blocking_gen_arg *gen = (struct dh_blocking_gen_arg *)arg;
|
93
|
+
gen->result = DH_generate_parameters_ex(gen->dh, gen->size, gen->gen, gen->cb);
|
94
|
+
return 0;
|
95
|
+
}
|
96
|
+
|
97
|
+
static DH *
|
98
|
+
dh_generate(int size, int gen)
|
99
|
+
{
|
100
|
+
struct ossl_generate_cb_arg cb_arg = { 0 };
|
101
|
+
struct dh_blocking_gen_arg gen_arg;
|
102
|
+
DH *dh = DH_new();
|
103
|
+
BN_GENCB *cb = BN_GENCB_new();
|
104
|
+
|
105
|
+
if (!dh || !cb) {
|
106
|
+
DH_free(dh);
|
107
|
+
BN_GENCB_free(cb);
|
108
|
+
return NULL;
|
109
|
+
}
|
110
|
+
|
111
|
+
if (rb_block_given_p())
|
112
|
+
cb_arg.yield = 1;
|
113
|
+
BN_GENCB_set(cb, ossl_generate_cb_2, &cb_arg);
|
114
|
+
gen_arg.dh = dh;
|
115
|
+
gen_arg.size = size;
|
116
|
+
gen_arg.gen = gen;
|
117
|
+
gen_arg.cb = cb;
|
118
|
+
if (cb_arg.yield == 1) {
|
119
|
+
/* we cannot release GVL when callback proc is supplied */
|
120
|
+
dh_blocking_gen(&gen_arg);
|
121
|
+
} else {
|
122
|
+
/* there's a chance to unblock */
|
123
|
+
rb_thread_call_without_gvl(dh_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg);
|
124
|
+
}
|
125
|
+
|
126
|
+
BN_GENCB_free(cb);
|
127
|
+
if (!gen_arg.result) {
|
128
|
+
DH_free(dh);
|
129
|
+
if (cb_arg.state) {
|
130
|
+
/* Clear OpenSSL error queue before re-raising. */
|
131
|
+
ossl_clear_error();
|
132
|
+
rb_jump_tag(cb_arg.state);
|
133
|
+
}
|
134
|
+
return NULL;
|
135
|
+
}
|
136
|
+
|
137
|
+
if (!DH_generate_key(dh)) {
|
138
|
+
DH_free(dh);
|
139
|
+
return NULL;
|
140
|
+
}
|
141
|
+
|
142
|
+
return dh;
|
143
|
+
}
|
144
|
+
|
145
|
+
/*
|
146
|
+
* call-seq:
|
147
|
+
* DH.generate(size [, generator]) -> dh
|
148
|
+
*
|
149
|
+
* Creates a new DH instance from scratch by generating the private and public
|
150
|
+
* components alike.
|
151
|
+
*
|
152
|
+
* === Parameters
|
153
|
+
* * _size_ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure.
|
154
|
+
* * _generator_ is a small number > 1, typically 2 or 5.
|
155
|
+
*
|
156
|
+
*/
|
157
|
+
static VALUE
|
158
|
+
ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
|
159
|
+
{
|
160
|
+
DH *dh ;
|
161
|
+
int g = 2;
|
162
|
+
VALUE size, gen, obj;
|
163
|
+
|
164
|
+
if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) {
|
165
|
+
g = NUM2INT(gen);
|
166
|
+
}
|
167
|
+
dh = dh_generate(NUM2INT(size), g);
|
168
|
+
obj = dh_instance(klass, dh);
|
169
|
+
if (obj == Qfalse) {
|
170
|
+
DH_free(dh);
|
171
|
+
ossl_raise(eDHError, NULL);
|
172
|
+
}
|
173
|
+
|
174
|
+
return obj;
|
175
|
+
}
|
176
|
+
|
177
|
+
/*
|
178
|
+
* call-seq:
|
179
|
+
* DH.new -> dh
|
180
|
+
* DH.new(string) -> dh
|
181
|
+
* DH.new(size [, generator]) -> dh
|
182
|
+
*
|
183
|
+
* Either generates a DH instance from scratch or by reading already existing
|
184
|
+
* DH parameters from _string_. Note that when reading a DH instance from
|
185
|
+
* data that was encoded from a DH instance by using DH#to_pem or DH#to_der
|
186
|
+
* the result will *not* contain a public/private key pair yet. This needs to
|
187
|
+
* be generated using DH#generate_key! first.
|
188
|
+
*
|
189
|
+
* === Parameters
|
190
|
+
* * _size_ is an integer representing the desired key size. Keys smaller than 1024 bits should be considered insecure.
|
191
|
+
* * _generator_ is a small number > 1, typically 2 or 5.
|
192
|
+
* * _string_ contains the DER or PEM encoded key.
|
193
|
+
*
|
194
|
+
* === Examples
|
195
|
+
* DH.new # -> dh
|
196
|
+
* DH.new(1024) # -> dh
|
197
|
+
* DH.new(1024, 5) # -> dh
|
198
|
+
* #Reading DH parameters
|
199
|
+
* dh = DH.new(File.read('parameters.pem')) # -> dh, but no public/private key yet
|
200
|
+
* dh.generate_key! # -> dh with public and private key
|
201
|
+
*/
|
202
|
+
static VALUE
|
203
|
+
ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
|
204
|
+
{
|
205
|
+
EVP_PKEY *pkey;
|
206
|
+
DH *dh;
|
207
|
+
int g = 2;
|
208
|
+
BIO *in;
|
209
|
+
VALUE arg, gen;
|
210
|
+
|
211
|
+
GetPKey(self, pkey);
|
212
|
+
if(rb_scan_args(argc, argv, "02", &arg, &gen) == 0) {
|
213
|
+
dh = DH_new();
|
214
|
+
}
|
215
|
+
else if (RB_INTEGER_TYPE_P(arg)) {
|
216
|
+
if (!NIL_P(gen)) {
|
217
|
+
g = NUM2INT(gen);
|
218
|
+
}
|
219
|
+
if (!(dh = dh_generate(NUM2INT(arg), g))) {
|
220
|
+
ossl_raise(eDHError, NULL);
|
221
|
+
}
|
222
|
+
}
|
223
|
+
else {
|
224
|
+
arg = ossl_to_der_if_possible(arg);
|
225
|
+
in = ossl_obj2bio(&arg);
|
226
|
+
dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
|
227
|
+
if (!dh){
|
228
|
+
OSSL_BIO_reset(in);
|
229
|
+
dh = d2i_DHparams_bio(in, NULL);
|
230
|
+
}
|
231
|
+
BIO_free(in);
|
232
|
+
if (!dh) {
|
233
|
+
ossl_raise(eDHError, NULL);
|
234
|
+
}
|
235
|
+
}
|
236
|
+
if (!EVP_PKEY_assign_DH(pkey, dh)) {
|
237
|
+
DH_free(dh);
|
238
|
+
ossl_raise(eDHError, NULL);
|
239
|
+
}
|
240
|
+
return self;
|
241
|
+
}
|
242
|
+
|
243
|
+
static VALUE
|
244
|
+
ossl_dh_initialize_copy(VALUE self, VALUE other)
|
245
|
+
{
|
246
|
+
EVP_PKEY *pkey;
|
247
|
+
DH *dh, *dh_other;
|
248
|
+
const BIGNUM *pub, *priv;
|
249
|
+
|
250
|
+
GetPKey(self, pkey);
|
251
|
+
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
|
252
|
+
ossl_raise(eDHError, "DH already initialized");
|
253
|
+
GetDH(other, dh_other);
|
254
|
+
|
255
|
+
dh = DHparams_dup(dh_other);
|
256
|
+
if (!dh)
|
257
|
+
ossl_raise(eDHError, "DHparams_dup");
|
258
|
+
EVP_PKEY_assign_DH(pkey, dh);
|
259
|
+
|
260
|
+
DH_get0_key(dh_other, &pub, &priv);
|
261
|
+
if (pub) {
|
262
|
+
BIGNUM *pub2 = BN_dup(pub);
|
263
|
+
BIGNUM *priv2 = BN_dup(priv);
|
264
|
+
|
265
|
+
if (!pub2 || (priv && !priv2)) {
|
266
|
+
BN_clear_free(pub2);
|
267
|
+
BN_clear_free(priv2);
|
268
|
+
ossl_raise(eDHError, "BN_dup");
|
269
|
+
}
|
270
|
+
DH_set0_key(dh, pub2, priv2);
|
271
|
+
}
|
272
|
+
|
273
|
+
return self;
|
274
|
+
}
|
275
|
+
|
276
|
+
/*
|
277
|
+
* call-seq:
|
278
|
+
* dh.public? -> true | false
|
279
|
+
*
|
280
|
+
* Indicates whether this DH instance has a public key associated with it or
|
281
|
+
* not. The public key may be retrieved with DH#pub_key.
|
282
|
+
*/
|
283
|
+
static VALUE
|
284
|
+
ossl_dh_is_public(VALUE self)
|
285
|
+
{
|
286
|
+
DH *dh;
|
287
|
+
const BIGNUM *bn;
|
288
|
+
|
289
|
+
GetDH(self, dh);
|
290
|
+
DH_get0_key(dh, &bn, NULL);
|
291
|
+
|
292
|
+
return bn ? Qtrue : Qfalse;
|
293
|
+
}
|
294
|
+
|
295
|
+
/*
|
296
|
+
* call-seq:
|
297
|
+
* dh.private? -> true | false
|
298
|
+
*
|
299
|
+
* Indicates whether this DH instance has a private key associated with it or
|
300
|
+
* not. The private key may be retrieved with DH#priv_key.
|
301
|
+
*/
|
302
|
+
static VALUE
|
303
|
+
ossl_dh_is_private(VALUE self)
|
304
|
+
{
|
305
|
+
DH *dh;
|
306
|
+
const BIGNUM *bn;
|
307
|
+
|
308
|
+
GetDH(self, dh);
|
309
|
+
DH_get0_key(dh, NULL, &bn);
|
310
|
+
|
311
|
+
#if !defined(OPENSSL_NO_ENGINE)
|
312
|
+
return (bn || DH_get0_engine(dh)) ? Qtrue : Qfalse;
|
313
|
+
#else
|
314
|
+
return bn ? Qtrue : Qfalse;
|
315
|
+
#endif
|
316
|
+
}
|
317
|
+
|
318
|
+
/*
|
319
|
+
* call-seq:
|
320
|
+
* dh.export -> aString
|
321
|
+
* dh.to_pem -> aString
|
322
|
+
* dh.to_s -> aString
|
323
|
+
*
|
324
|
+
* Encodes this DH to its PEM encoding. Note that any existing per-session
|
325
|
+
* public/private keys will *not* get encoded, just the Diffie-Hellman
|
326
|
+
* parameters will be encoded.
|
327
|
+
*/
|
328
|
+
static VALUE
|
329
|
+
ossl_dh_export(VALUE self)
|
330
|
+
{
|
331
|
+
DH *dh;
|
332
|
+
BIO *out;
|
333
|
+
VALUE str;
|
334
|
+
|
335
|
+
GetDH(self, dh);
|
336
|
+
if (!(out = BIO_new(BIO_s_mem()))) {
|
337
|
+
ossl_raise(eDHError, NULL);
|
338
|
+
}
|
339
|
+
if (!PEM_write_bio_DHparams(out, dh)) {
|
340
|
+
BIO_free(out);
|
341
|
+
ossl_raise(eDHError, NULL);
|
342
|
+
}
|
343
|
+
str = ossl_membio2str(out);
|
344
|
+
|
345
|
+
return str;
|
346
|
+
}
|
347
|
+
|
348
|
+
/*
|
349
|
+
* call-seq:
|
350
|
+
* dh.to_der -> aString
|
351
|
+
*
|
352
|
+
* Encodes this DH to its DER encoding. Note that any existing per-session
|
353
|
+
* public/private keys will *not* get encoded, just the Diffie-Hellman
|
354
|
+
* parameters will be encoded.
|
355
|
+
|
356
|
+
*/
|
357
|
+
static VALUE
|
358
|
+
ossl_dh_to_der(VALUE self)
|
359
|
+
{
|
360
|
+
DH *dh;
|
361
|
+
unsigned char *p;
|
362
|
+
long len;
|
363
|
+
VALUE str;
|
364
|
+
|
365
|
+
GetDH(self, dh);
|
366
|
+
if((len = i2d_DHparams(dh, NULL)) <= 0)
|
367
|
+
ossl_raise(eDHError, NULL);
|
368
|
+
str = rb_str_new(0, len);
|
369
|
+
p = (unsigned char *)RSTRING_PTR(str);
|
370
|
+
if(i2d_DHparams(dh, &p) < 0)
|
371
|
+
ossl_raise(eDHError, NULL);
|
372
|
+
ossl_str_adjust(str, p);
|
373
|
+
|
374
|
+
return str;
|
375
|
+
}
|
376
|
+
|
377
|
+
/*
|
378
|
+
* call-seq:
|
379
|
+
* dh.params -> hash
|
380
|
+
*
|
381
|
+
* Stores all parameters of key to the hash
|
382
|
+
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
|
383
|
+
* Don't use :-)) (I's up to you)
|
384
|
+
*/
|
385
|
+
static VALUE
|
386
|
+
ossl_dh_get_params(VALUE self)
|
387
|
+
{
|
388
|
+
DH *dh;
|
389
|
+
VALUE hash;
|
390
|
+
const BIGNUM *p, *q, *g, *pub_key, *priv_key;
|
391
|
+
|
392
|
+
GetDH(self, dh);
|
393
|
+
DH_get0_pqg(dh, &p, &q, &g);
|
394
|
+
DH_get0_key(dh, &pub_key, &priv_key);
|
395
|
+
|
396
|
+
hash = rb_hash_new();
|
397
|
+
rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p));
|
398
|
+
rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q));
|
399
|
+
rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(g));
|
400
|
+
rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pub_key));
|
401
|
+
rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(priv_key));
|
402
|
+
|
403
|
+
return hash;
|
404
|
+
}
|
405
|
+
|
406
|
+
/*
|
407
|
+
* call-seq:
|
408
|
+
* dh.to_text -> aString
|
409
|
+
*
|
410
|
+
* Prints all parameters of key to buffer
|
411
|
+
* INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
|
412
|
+
* Don't use :-)) (I's up to you)
|
413
|
+
*/
|
414
|
+
static VALUE
|
415
|
+
ossl_dh_to_text(VALUE self)
|
416
|
+
{
|
417
|
+
DH *dh;
|
418
|
+
BIO *out;
|
419
|
+
VALUE str;
|
420
|
+
|
421
|
+
GetDH(self, dh);
|
422
|
+
if (!(out = BIO_new(BIO_s_mem()))) {
|
423
|
+
ossl_raise(eDHError, NULL);
|
424
|
+
}
|
425
|
+
if (!DHparams_print(out, dh)) {
|
426
|
+
BIO_free(out);
|
427
|
+
ossl_raise(eDHError, NULL);
|
428
|
+
}
|
429
|
+
str = ossl_membio2str(out);
|
430
|
+
|
431
|
+
return str;
|
432
|
+
}
|
433
|
+
|
434
|
+
/*
|
435
|
+
* call-seq:
|
436
|
+
* dh.public_key -> aDH
|
437
|
+
*
|
438
|
+
* Returns a new DH instance that carries just the public information, i.e.
|
439
|
+
* the prime _p_ and the generator _g_, but no public/private key yet. Such
|
440
|
+
* a pair may be generated using DH#generate_key!. The "public key" needed
|
441
|
+
* for a key exchange with DH#compute_key is considered as per-session
|
442
|
+
* information and may be retrieved with DH#pub_key once a key pair has
|
443
|
+
* been generated.
|
444
|
+
* If the current instance already contains private information (and thus a
|
445
|
+
* valid public/private key pair), this information will no longer be present
|
446
|
+
* in the new instance generated by DH#public_key. This feature is helpful for
|
447
|
+
* publishing the Diffie-Hellman parameters without leaking any of the private
|
448
|
+
* per-session information.
|
449
|
+
*
|
450
|
+
* === Example
|
451
|
+
* dh = OpenSSL::PKey::DH.new(2048) # has public and private key set
|
452
|
+
* public_key = dh.public_key # contains only prime and generator
|
453
|
+
* parameters = public_key.to_der # it's safe to publish this
|
454
|
+
*/
|
455
|
+
static VALUE
|
456
|
+
ossl_dh_to_public_key(VALUE self)
|
457
|
+
{
|
458
|
+
DH *orig_dh, *dh;
|
459
|
+
VALUE obj;
|
460
|
+
|
461
|
+
GetDH(self, orig_dh);
|
462
|
+
dh = DHparams_dup(orig_dh); /* err check perfomed by dh_instance */
|
463
|
+
obj = dh_instance(rb_obj_class(self), dh);
|
464
|
+
if (obj == Qfalse) {
|
465
|
+
DH_free(dh);
|
466
|
+
ossl_raise(eDHError, NULL);
|
467
|
+
}
|
468
|
+
|
469
|
+
return obj;
|
470
|
+
}
|
471
|
+
|
472
|
+
/*
|
473
|
+
* call-seq:
|
474
|
+
* dh.params_ok? -> true | false
|
475
|
+
*
|
476
|
+
* Validates the Diffie-Hellman parameters associated with this instance.
|
477
|
+
* It checks whether a safe prime and a suitable generator are used. If this
|
478
|
+
* is not the case, +false+ is returned.
|
479
|
+
*/
|
480
|
+
static VALUE
|
481
|
+
ossl_dh_check_params(VALUE self)
|
482
|
+
{
|
483
|
+
DH *dh;
|
484
|
+
int codes;
|
485
|
+
|
486
|
+
GetDH(self, dh);
|
487
|
+
if (!DH_check(dh, &codes)) {
|
488
|
+
return Qfalse;
|
489
|
+
}
|
490
|
+
|
491
|
+
return codes == 0 ? Qtrue : Qfalse;
|
492
|
+
}
|
493
|
+
|
494
|
+
/*
|
495
|
+
* call-seq:
|
496
|
+
* dh.generate_key! -> self
|
497
|
+
*
|
498
|
+
* Generates a private and public key unless a private key already exists.
|
499
|
+
* If this DH instance was generated from public DH parameters (e.g. by
|
500
|
+
* encoding the result of DH#public_key), then this method needs to be
|
501
|
+
* called first in order to generate the per-session keys before performing
|
502
|
+
* the actual key exchange.
|
503
|
+
*
|
504
|
+
* === Example
|
505
|
+
* dh = OpenSSL::PKey::DH.new(2048)
|
506
|
+
* public_key = dh.public_key #contains no private/public key yet
|
507
|
+
* public_key.generate_key!
|
508
|
+
* puts public_key.private? # => true
|
509
|
+
*/
|
510
|
+
static VALUE
|
511
|
+
ossl_dh_generate_key(VALUE self)
|
512
|
+
{
|
513
|
+
DH *dh;
|
514
|
+
|
515
|
+
GetDH(self, dh);
|
516
|
+
if (!DH_generate_key(dh))
|
517
|
+
ossl_raise(eDHError, "Failed to generate key");
|
518
|
+
return self;
|
519
|
+
}
|
520
|
+
|
521
|
+
/*
|
522
|
+
* call-seq:
|
523
|
+
* dh.compute_key(pub_bn) -> aString
|
524
|
+
*
|
525
|
+
* Returns a String containing a shared secret computed from the other party's public value.
|
526
|
+
* See DH_compute_key() for further information.
|
527
|
+
*
|
528
|
+
* === Parameters
|
529
|
+
* * _pub_bn_ is a OpenSSL::BN, *not* the DH instance returned by
|
530
|
+
* DH#public_key as that contains the DH parameters only.
|
531
|
+
*/
|
532
|
+
static VALUE
|
533
|
+
ossl_dh_compute_key(VALUE self, VALUE pub)
|
534
|
+
{
|
535
|
+
DH *dh;
|
536
|
+
const BIGNUM *pub_key, *dh_p;
|
537
|
+
VALUE str;
|
538
|
+
int len;
|
539
|
+
|
540
|
+
GetDH(self, dh);
|
541
|
+
DH_get0_pqg(dh, &dh_p, NULL, NULL);
|
542
|
+
if (!dh_p)
|
543
|
+
ossl_raise(eDHError, "incomplete DH");
|
544
|
+
pub_key = GetBNPtr(pub);
|
545
|
+
len = DH_size(dh);
|
546
|
+
str = rb_str_new(0, len);
|
547
|
+
if ((len = DH_compute_key((unsigned char *)RSTRING_PTR(str), pub_key, dh)) < 0) {
|
548
|
+
ossl_raise(eDHError, NULL);
|
549
|
+
}
|
550
|
+
rb_str_set_len(str, len);
|
551
|
+
|
552
|
+
return str;
|
553
|
+
}
|
554
|
+
|
555
|
+
/*
|
556
|
+
* Document-method: OpenSSL::PKey::DH#set_pqg
|
557
|
+
* call-seq:
|
558
|
+
* dh.set_pqg(p, q, g) -> self
|
559
|
+
*
|
560
|
+
* Sets _p_, _q_, _g_ to the DH instance.
|
561
|
+
*/
|
562
|
+
OSSL_PKEY_BN_DEF3(dh, DH, pqg, p, q, g)
|
563
|
+
/*
|
564
|
+
* Document-method: OpenSSL::PKey::DH#set_key
|
565
|
+
* call-seq:
|
566
|
+
* dh.set_key(pub_key, priv_key) -> self
|
567
|
+
*
|
568
|
+
* Sets _pub_key_ and _priv_key_ for the DH instance. _priv_key_ may be +nil+.
|
569
|
+
*/
|
570
|
+
OSSL_PKEY_BN_DEF2(dh, DH, key, pub_key, priv_key)
|
571
|
+
|
572
|
+
/*
|
573
|
+
* INIT
|
574
|
+
*/
|
575
|
+
void
|
576
|
+
Init_ossl_dh(void)
|
577
|
+
{
|
578
|
+
#if 0
|
579
|
+
mPKey = rb_define_module_under(mOSSL, "PKey");
|
580
|
+
cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
|
581
|
+
ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
|
582
|
+
#endif
|
583
|
+
|
584
|
+
/* Document-class: OpenSSL::PKey::DHError
|
585
|
+
*
|
586
|
+
* Generic exception that is raised if an operation on a DH PKey
|
587
|
+
* fails unexpectedly or in case an instantiation of an instance of DH
|
588
|
+
* fails due to non-conformant input data.
|
589
|
+
*/
|
590
|
+
eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError);
|
591
|
+
/* Document-class: OpenSSL::PKey::DH
|
592
|
+
*
|
593
|
+
* An implementation of the Diffie-Hellman key exchange protocol based on
|
594
|
+
* discrete logarithms in finite fields, the same basis that DSA is built
|
595
|
+
* on.
|
596
|
+
*
|
597
|
+
* === Accessor methods for the Diffie-Hellman parameters
|
598
|
+
* DH#p::
|
599
|
+
* The prime (an OpenSSL::BN) of the Diffie-Hellman parameters.
|
600
|
+
* DH#g::
|
601
|
+
* The generator (an OpenSSL::BN) g of the Diffie-Hellman parameters.
|
602
|
+
* DH#pub_key::
|
603
|
+
* The per-session public key (an OpenSSL::BN) matching the private key.
|
604
|
+
* This needs to be passed to DH#compute_key.
|
605
|
+
* DH#priv_key::
|
606
|
+
* The per-session private key, an OpenSSL::BN.
|
607
|
+
*
|
608
|
+
* === Example of a key exchange
|
609
|
+
* dh1 = OpenSSL::PKey::DH.new(2048)
|
610
|
+
* der = dh1.public_key.to_der #you may send this publicly to the participating party
|
611
|
+
* dh2 = OpenSSL::PKey::DH.new(der)
|
612
|
+
* dh2.generate_key! #generate the per-session key pair
|
613
|
+
* symm_key1 = dh1.compute_key(dh2.pub_key)
|
614
|
+
* symm_key2 = dh2.compute_key(dh1.pub_key)
|
615
|
+
*
|
616
|
+
* puts symm_key1 == symm_key2 # => true
|
617
|
+
*/
|
618
|
+
cDH = rb_define_class_under(mPKey, "DH", cPKey);
|
619
|
+
rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1);
|
620
|
+
rb_define_method(cDH, "initialize", ossl_dh_initialize, -1);
|
621
|
+
rb_define_method(cDH, "initialize_copy", ossl_dh_initialize_copy, 1);
|
622
|
+
rb_define_method(cDH, "public?", ossl_dh_is_public, 0);
|
623
|
+
rb_define_method(cDH, "private?", ossl_dh_is_private, 0);
|
624
|
+
rb_define_method(cDH, "to_text", ossl_dh_to_text, 0);
|
625
|
+
rb_define_method(cDH, "export", ossl_dh_export, 0);
|
626
|
+
rb_define_alias(cDH, "to_pem", "export");
|
627
|
+
rb_define_alias(cDH, "to_s", "export");
|
628
|
+
rb_define_method(cDH, "to_der", ossl_dh_to_der, 0);
|
629
|
+
rb_define_method(cDH, "public_key", ossl_dh_to_public_key, 0);
|
630
|
+
rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0);
|
631
|
+
rb_define_method(cDH, "generate_key!", ossl_dh_generate_key, 0);
|
632
|
+
rb_define_method(cDH, "compute_key", ossl_dh_compute_key, 1);
|
633
|
+
|
634
|
+
DEF_OSSL_PKEY_BN(cDH, dh, p);
|
635
|
+
DEF_OSSL_PKEY_BN(cDH, dh, q);
|
636
|
+
DEF_OSSL_PKEY_BN(cDH, dh, g);
|
637
|
+
DEF_OSSL_PKEY_BN(cDH, dh, pub_key);
|
638
|
+
DEF_OSSL_PKEY_BN(cDH, dh, priv_key);
|
639
|
+
rb_define_method(cDH, "set_pqg", ossl_dh_set_pqg, 3);
|
640
|
+
rb_define_method(cDH, "set_key", ossl_dh_set_key, 2);
|
641
|
+
|
642
|
+
rb_define_method(cDH, "params", ossl_dh_get_params, 0);
|
643
|
+
}
|
644
|
+
|
645
|
+
#else /* defined NO_DH */
|
646
|
+
void
|
647
|
+
Init_ossl_dh(void)
|
648
|
+
{
|
649
|
+
}
|
650
|
+
#endif /* NO_DH */
|