PageRenderTime 255ms CodeModel.GetById 91ms app.highlight 87ms RepoModel.GetById 35ms app.codeStats 0ms

/source/ruby-1.9.2-p180/ext/openssl/ossl_pkey_dh.c

https://github.com/akiernan/omnibus
C | 532 lines | 344 code | 65 blank | 123 comment | 47 complexity | 6ef02b33af215af0914ccdde3f2714b7 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause
  1/*
  2 * $Id: ossl_pkey_dh.c 27440 2010-04-22 08:21:01Z nobu $
  3 * 'OpenSSL for Ruby' project
  4 * Copyright (C) 2001-2002  Michal Rokos <m.rokos@sh.cvut.cz>
  5 * All rights reserved.
  6 */
  7/*
  8 * This program is licenced under the same licence as Ruby.
  9 * (See the file 'LICENCE'.)
 10 */
 11#if !defined(OPENSSL_NO_DH)
 12
 13#include "ossl.h"
 14
 15#define GetPKeyDH(obj, pkey) do { \
 16    GetPKey(obj, pkey); \
 17    if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) { /* PARANOIA? */ \
 18	ossl_raise(rb_eRuntimeError, "THIS IS NOT A DH!") ; \
 19    } \
 20} while (0)
 21
 22#define DH_HAS_PRIVATE(dh) ((dh)->priv_key)
 23
 24#ifdef OSSL_ENGINE_ENABLED
 25#  define DH_PRIVATE(dh) (DH_HAS_PRIVATE(dh) || (dh)->engine)
 26#else
 27#  define DH_PRIVATE(dh) DH_HAS_PRIVATE(dh)
 28#endif
 29
 30
 31/*
 32 * Classes
 33 */
 34VALUE cDH;
 35VALUE eDHError;
 36
 37/*
 38 * Public
 39 */
 40static VALUE
 41dh_instance(VALUE klass, DH *dh)
 42{
 43    EVP_PKEY *pkey;
 44    VALUE obj;
 45
 46    if (!dh) {
 47	return Qfalse;
 48    }
 49    if (!(pkey = EVP_PKEY_new())) {
 50	return Qfalse;
 51    }
 52    if (!EVP_PKEY_assign_DH(pkey, dh)) {
 53	EVP_PKEY_free(pkey);
 54	return Qfalse;
 55    }
 56    WrapPKey(klass, obj, pkey);
 57
 58    return obj;
 59}
 60
 61VALUE
 62ossl_dh_new(EVP_PKEY *pkey)
 63{
 64    VALUE obj;
 65
 66    if (!pkey) {
 67	obj = dh_instance(cDH, DH_new());
 68    } else {
 69	if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DH) {
 70	    ossl_raise(rb_eTypeError, "Not a DH key!");
 71	}
 72	WrapPKey(cDH, obj, pkey);
 73    }
 74    if (obj == Qfalse) {
 75	ossl_raise(eDHError, NULL);
 76    }
 77
 78    return obj;
 79}
 80
 81/*
 82 * Private
 83 */
 84static DH *
 85dh_generate(int size, int gen)
 86{
 87    DH *dh;
 88
 89    dh = DH_generate_parameters(size, gen,
 90	    rb_block_given_p() ? ossl_generate_cb : NULL,
 91	    NULL);
 92    if (!dh) return 0;
 93
 94    if (!DH_generate_key(dh)) {
 95	DH_free(dh);
 96	return 0;
 97    }
 98
 99    return dh;
100}
101
102/*
103 *  call-seq:
104 *     DH.generate(size [, generator]) -> dh
105 *
106 *  === Parameters
107 *  * +size+ is an integer representing the desired key size.  Keys smaller than 1024 should be considered insecure.
108 *  * +generator+ is a small number > 1, typically 2 or 5.
109 *
110 */
111static VALUE
112ossl_dh_s_generate(int argc, VALUE *argv, VALUE klass)
113{
114    DH *dh ;
115    int g = 2;
116    VALUE size, gen, obj;
117
118    if (rb_scan_args(argc, argv, "11", &size, &gen) == 2) {
119	g = NUM2INT(gen);
120    }
121    dh = dh_generate(NUM2INT(size), g);
122    obj = dh_instance(klass, dh);
123    if (obj == Qfalse) {
124	DH_free(dh);
125	ossl_raise(eDHError, NULL);
126    }
127
128    return obj;
129}
130
131/*
132 *  call-seq:
133 *     DH.new([size [, generator] | string]) -> dh
134 *
135 *  === Parameters
136 *  * +size+ is an integer representing the desired key size.  Keys smaller than 1024 should be considered insecure.
137 *  * +generator+ is a small number > 1, typically 2 or 5.
138 *  * +string+ contains the DER or PEM encoded key.
139 *
140 *  === Examples
141 *  * DH.new -> dh
142 *  * DH.new(1024) -> dh
143 *  * DH.new(1024, 5) -> dh
144 *  * DH.new(File.read('key.pem')) -> dh
145 */
146static VALUE
147ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
148{
149    EVP_PKEY *pkey;
150    DH *dh;
151    int g = 2;
152    BIO *in;
153    VALUE arg, gen;
154
155    GetPKey(self, pkey);
156    if(rb_scan_args(argc, argv, "02", &arg, &gen) == 0) {
157      dh = DH_new();
158    }
159    else if (FIXNUM_P(arg)) {
160	if (!NIL_P(gen)) {
161	    g = NUM2INT(gen);
162	}
163	if (!(dh = dh_generate(FIX2INT(arg), g))) {
164	    ossl_raise(eDHError, NULL);
165	}
166    }
167    else {
168	arg = ossl_to_der_if_possible(arg);
169	in = ossl_obj2bio(arg);
170	dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
171	if (!dh){
172	    (void)BIO_reset(in);
173	    dh = d2i_DHparams_bio(in, NULL);
174	}
175	BIO_free(in);
176	if (!dh) ossl_raise(eDHError, NULL);
177    }
178    if (!EVP_PKEY_assign_DH(pkey, dh)) {
179	DH_free(dh);
180	ossl_raise(eDHError, NULL);
181    }
182    return self;
183}
184
185/*
186 *  call-seq:
187 *     dh.public? -> true | false
188 *
189 */
190static VALUE
191ossl_dh_is_public(VALUE self)
192{
193    EVP_PKEY *pkey;
194
195    GetPKeyDH(self, pkey);
196
197    return (pkey->pkey.dh->pub_key) ? Qtrue : Qfalse;
198}
199
200/*
201 *  call-seq:
202 *     dh.private? -> true | false
203 *
204 */
205static VALUE
206ossl_dh_is_private(VALUE self)
207{
208    EVP_PKEY *pkey;
209
210    GetPKeyDH(self, pkey);
211
212    return (DH_PRIVATE(pkey->pkey.dh)) ? Qtrue : Qfalse;
213}
214
215/*
216 *  call-seq:
217 *     dh.to_pem -> aString
218 *
219 */
220static VALUE
221ossl_dh_export(VALUE self)
222{
223    EVP_PKEY *pkey;
224    BIO *out;
225    VALUE str;
226
227    GetPKeyDH(self, pkey);
228    if (!(out = BIO_new(BIO_s_mem()))) {
229	ossl_raise(eDHError, NULL);
230    }
231    if (!PEM_write_bio_DHparams(out, pkey->pkey.dh)) {
232	BIO_free(out);
233	ossl_raise(eDHError, NULL);
234    }
235    str = ossl_membio2str(out);
236
237    return str;
238}
239
240/*
241 *  call-seq:
242 *     dh.to_der -> aString
243 *
244 */
245static VALUE
246ossl_dh_to_der(VALUE self)
247{
248    EVP_PKEY *pkey;
249    unsigned char *p;
250    long len;
251    VALUE str;
252
253    GetPKeyDH(self, pkey);
254    if((len = i2d_DHparams(pkey->pkey.dh, NULL)) <= 0)
255	ossl_raise(eDHError, NULL);
256    str = rb_str_new(0, len);
257    p = (unsigned char *)RSTRING_PTR(str);
258    if(i2d_DHparams(pkey->pkey.dh, &p) < 0)
259	ossl_raise(eDHError, NULL);
260    ossl_str_adjust(str, p);
261
262    return str;
263}
264
265/*
266 *  call-seq:
267 *     dh.params -> hash
268 *
269 * Stores all parameters of key to the hash
270 * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
271 * Don't use :-)) (I's up to you)
272 */
273static VALUE
274ossl_dh_get_params(VALUE self)
275{
276    EVP_PKEY *pkey;
277    VALUE hash;
278
279    GetPKeyDH(self, pkey);
280
281    hash = rb_hash_new();
282
283    rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dh->p));
284    rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dh->g));
285    rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dh->pub_key));
286    rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dh->priv_key));
287
288    return hash;
289}
290
291/*
292 *  call-seq:
293 *     dh.to_text -> aString
294 *
295 * Prints all parameters of key to buffer
296 * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
297 * Don't use :-)) (I's up to you)
298 */
299static VALUE
300ossl_dh_to_text(VALUE self)
301{
302    EVP_PKEY *pkey;
303    BIO *out;
304    VALUE str;
305
306    GetPKeyDH(self, pkey);
307    if (!(out = BIO_new(BIO_s_mem()))) {
308	ossl_raise(eDHError, NULL);
309    }
310    if (!DHparams_print(out, pkey->pkey.dh)) {
311	BIO_free(out);
312	ossl_raise(eDHError, NULL);
313    }
314    str = ossl_membio2str(out);
315
316    return str;
317}
318
319/*
320 *  call-seq:
321 *     dh.public_key -> aDH
322 *
323 *  Makes new instance DH PUBLIC_KEY from PRIVATE_KEY
324 */
325static VALUE
326ossl_dh_to_public_key(VALUE self)
327{
328    EVP_PKEY *pkey;
329    DH *dh;
330    VALUE obj;
331
332    GetPKeyDH(self, pkey);
333    dh = DHparams_dup(pkey->pkey.dh); /* err check perfomed by dh_instance */
334    obj = dh_instance(CLASS_OF(self), dh);
335    if (obj == Qfalse) {
336	DH_free(dh);
337	ossl_raise(eDHError, NULL);
338    }
339
340    return obj;
341}
342
343/*
344 *  call-seq:
345 *     dh.check_params -> true | false
346 *
347 */
348static VALUE
349ossl_dh_check_params(VALUE self)
350{
351    DH *dh;
352    EVP_PKEY *pkey;
353    int codes;
354
355    GetPKeyDH(self, pkey);
356    dh = pkey->pkey.dh;
357
358    if (!DH_check(dh, &codes)) {
359	return Qfalse;
360    }
361
362    return codes == 0 ? Qtrue : Qfalse;
363}
364
365/*
366 *  call-seq:
367 *     dh.generate_key -> self
368 *
369 */
370static VALUE
371ossl_dh_generate_key(VALUE self)
372{
373    DH *dh;
374    EVP_PKEY *pkey;
375
376    GetPKeyDH(self, pkey);
377    dh = pkey->pkey.dh;
378
379    if (!DH_generate_key(dh))
380	ossl_raise(eDHError, "Failed to generate key");
381    return self;
382}
383
384/*
385 *  call-seq:
386 *     dh.compute_key(pub_bn) -> aString
387 *
388 *  === Parameters
389 *  * +pub_bn+ is a OpenSSL::BN.
390 *
391 *  Returns aString containing a shared secret computed from the other parties public value.
392 *
393 *  See DH_compute_key() for further information.
394 *
395 */
396static VALUE
397ossl_dh_compute_key(VALUE self, VALUE pub)
398{
399    DH *dh;
400    EVP_PKEY *pkey;
401    BIGNUM *pub_key;
402    VALUE str;
403    int len;
404
405    GetPKeyDH(self, pkey);
406    dh = pkey->pkey.dh;
407    pub_key = GetBNPtr(pub);
408    len = DH_size(dh);
409    str = rb_str_new(0, len);
410    if ((len = DH_compute_key((unsigned char *)RSTRING_PTR(str), pub_key, dh)) < 0) {
411	ossl_raise(eDHError, NULL);
412    }
413    rb_str_set_len(str, len);
414
415    return str;
416}
417
418OSSL_PKEY_BN(dh, p)
419OSSL_PKEY_BN(dh, g)
420OSSL_PKEY_BN(dh, pub_key)
421OSSL_PKEY_BN(dh, priv_key)
422
423/*
424 * -----BEGIN DH PARAMETERS-----
425 * MEYCQQD0zXHljRg/mJ9PYLACLv58Cd8VxBxxY7oEuCeURMiTqEhMym16rhhKgZG2
426 * zk2O9uUIBIxSj+NKMURHGaFKyIvLAgEC
427 * -----END DH PARAMETERS-----
428 */
429static unsigned char DEFAULT_DH_512_PRIM[] = {
430    0xf4, 0xcd, 0x71, 0xe5, 0x8d, 0x18, 0x3f, 0x98,
431    0x9f, 0x4f, 0x60, 0xb0, 0x02, 0x2e, 0xfe, 0x7c,
432    0x09, 0xdf, 0x15, 0xc4, 0x1c, 0x71, 0x63, 0xba,
433    0x04, 0xb8, 0x27, 0x94, 0x44, 0xc8, 0x93, 0xa8,
434    0x48, 0x4c, 0xca, 0x6d, 0x7a, 0xae, 0x18, 0x4a,
435    0x81, 0x91, 0xb6, 0xce, 0x4d, 0x8e, 0xf6, 0xe5,
436    0x08, 0x04, 0x8c, 0x52, 0x8f, 0xe3, 0x4a, 0x31,
437    0x44, 0x47, 0x19, 0xa1, 0x4a, 0xc8, 0x8b, 0xcb,
438};
439static unsigned char DEFAULT_DH_512_GEN[] = { 0x02 };
440DH *OSSL_DEFAULT_DH_512 = NULL;
441
442/*
443 * -----BEGIN DH PARAMETERS-----
444 * MIGHAoGBAJ0lOVy0VIr/JebWn0zDwY2h+rqITFOpdNr6ugsgvkDXuucdcChhYExJ
445 * AV/ZD2AWPbrTqV76mGRgJg4EddgT1zG0jq3rnFdMj2XzkBYx3BVvfR0Arnby0RHR
446 * T4h7KZ/2zmjvV+eF8kBUHBJAojUlzxKj4QeO2x20FP9X5xmNUXeDAgEC
447 * -----END DH PARAMETERS-----
448 */
449static unsigned char DEFAULT_DH_1024_PRIM[] = {
450    0x9d, 0x25, 0x39, 0x5c, 0xb4, 0x54, 0x8a, 0xff,
451    0x25, 0xe6, 0xd6, 0x9f, 0x4c, 0xc3, 0xc1, 0x8d,
452    0xa1, 0xfa, 0xba, 0x88, 0x4c, 0x53, 0xa9, 0x74,
453    0xda, 0xfa, 0xba, 0x0b, 0x20, 0xbe, 0x40, 0xd7,
454    0xba, 0xe7, 0x1d, 0x70, 0x28, 0x61, 0x60, 0x4c,
455    0x49, 0x01, 0x5f, 0xd9, 0x0f, 0x60, 0x16, 0x3d,
456    0xba, 0xd3, 0xa9, 0x5e, 0xfa, 0x98, 0x64, 0x60,
457    0x26, 0x0e, 0x04, 0x75, 0xd8, 0x13, 0xd7, 0x31,
458    0xb4, 0x8e, 0xad, 0xeb, 0x9c, 0x57, 0x4c, 0x8f,
459    0x65, 0xf3, 0x90, 0x16, 0x31, 0xdc, 0x15, 0x6f,
460    0x7d, 0x1d, 0x00, 0xae, 0x76, 0xf2, 0xd1, 0x11,
461    0xd1, 0x4f, 0x88, 0x7b, 0x29, 0x9f, 0xf6, 0xce,
462    0x68, 0xef, 0x57, 0xe7, 0x85, 0xf2, 0x40, 0x54,
463    0x1c, 0x12, 0x40, 0xa2, 0x35, 0x25, 0xcf, 0x12,
464    0xa3, 0xe1, 0x07, 0x8e, 0xdb, 0x1d, 0xb4, 0x14,
465    0xff, 0x57, 0xe7, 0x19, 0x8d, 0x51, 0x77, 0x83
466};
467static unsigned char DEFAULT_DH_1024_GEN[] = { 0x02 };
468DH *OSSL_DEFAULT_DH_1024 = NULL;
469
470static DH*
471ossl_create_dh(unsigned char *p, size_t plen, unsigned char *g, size_t glen)
472{
473    DH *dh;
474
475    if ((dh = DH_new()) == NULL) ossl_raise(eDHError, NULL);
476    dh->p = BN_bin2bn(p, plen, NULL);
477    dh->g = BN_bin2bn(g, glen, NULL);
478    if (dh->p == NULL || dh->g == NULL){
479        DH_free(dh);
480	ossl_raise(eDHError, NULL);
481    }
482
483    return dh;
484}
485
486/*
487 * INIT
488 */
489void
490Init_ossl_dh()
491{
492#if 0 /* let rdoc know about mOSSL and mPKey */
493    mOSSL = rb_define_module("OpenSSL");
494    mPKey = rb_define_module_under(mOSSL, "PKey");
495#endif
496
497    eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError);
498    cDH = rb_define_class_under(mPKey, "DH", cPKey);
499    rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1);
500    rb_define_method(cDH, "initialize", ossl_dh_initialize, -1);
501    rb_define_method(cDH, "public?", ossl_dh_is_public, 0);
502    rb_define_method(cDH, "private?", ossl_dh_is_private, 0);
503    rb_define_method(cDH, "to_text", ossl_dh_to_text, 0);
504    rb_define_method(cDH, "export", ossl_dh_export, 0);
505    rb_define_alias(cDH, "to_pem", "export");
506    rb_define_alias(cDH, "to_s", "export");
507    rb_define_method(cDH, "to_der", ossl_dh_to_der, 0);
508    rb_define_method(cDH, "public_key", ossl_dh_to_public_key, 0);
509    rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0);
510    rb_define_method(cDH, "generate_key!", ossl_dh_generate_key, 0);
511    rb_define_method(cDH, "compute_key", ossl_dh_compute_key, 1);
512    DEF_OSSL_PKEY_BN(cDH, dh, p);
513    DEF_OSSL_PKEY_BN(cDH, dh, g);
514    DEF_OSSL_PKEY_BN(cDH, dh, pub_key);
515    DEF_OSSL_PKEY_BN(cDH, dh, priv_key);
516    rb_define_method(cDH, "params", ossl_dh_get_params, 0);
517
518    OSSL_DEFAULT_DH_512 = ossl_create_dh(
519	DEFAULT_DH_512_PRIM, sizeof(DEFAULT_DH_512_PRIM),
520	DEFAULT_DH_512_GEN, sizeof(DEFAULT_DH_512_GEN));
521    OSSL_DEFAULT_DH_1024 = ossl_create_dh(
522	DEFAULT_DH_1024_PRIM, sizeof(DEFAULT_DH_1024_PRIM),
523	DEFAULT_DH_1024_GEN, sizeof(DEFAULT_DH_1024_GEN));
524}
525
526#else /* defined NO_DH */
527void
528Init_ossl_dh()
529{
530}
531#endif /* NO_DH */
532