00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #if !defined(OPENSSL_NO_DSA)
00012
00013 #include "ossl.h"
00014
00015 #define GetPKeyDSA(obj, pkey) do { \
00016 GetPKey((obj), (pkey)); \
00017 if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_DSA) { \
00018 ossl_raise(rb_eRuntimeError, "THIS IS NOT A DSA!"); \
00019 } \
00020 } while (0)
00021
00022 #define DSA_HAS_PRIVATE(dsa) ((dsa)->priv_key)
00023 #define DSA_PRIVATE(obj,dsa) (DSA_HAS_PRIVATE(dsa)||OSSL_PKEY_IS_PRIVATE(obj))
00024
00025
00026
00027
00028 VALUE cDSA;
00029 VALUE eDSAError;
00030
00031
00032
00033
00034 static VALUE
00035 dsa_instance(VALUE klass, DSA *dsa)
00036 {
00037 EVP_PKEY *pkey;
00038 VALUE obj;
00039
00040 if (!dsa) {
00041 return Qfalse;
00042 }
00043 if (!(pkey = EVP_PKEY_new())) {
00044 return Qfalse;
00045 }
00046 if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
00047 EVP_PKEY_free(pkey);
00048 return Qfalse;
00049 }
00050 WrapPKey(klass, obj, pkey);
00051
00052 return obj;
00053 }
00054
00055 VALUE
00056 ossl_dsa_new(EVP_PKEY *pkey)
00057 {
00058 VALUE obj;
00059
00060 if (!pkey) {
00061 obj = dsa_instance(cDSA, DSA_new());
00062 } else {
00063 if (EVP_PKEY_type(pkey->type) != EVP_PKEY_DSA) {
00064 ossl_raise(rb_eTypeError, "Not a DSA key!");
00065 }
00066 WrapPKey(cDSA, obj, pkey);
00067 }
00068 if (obj == Qfalse) {
00069 ossl_raise(eDSAError, NULL);
00070 }
00071
00072 return obj;
00073 }
00074
00075
00076
00077
00078 #if defined(HAVE_DSA_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB
00079 struct dsa_blocking_gen_arg {
00080 DSA *dsa;
00081 int size;
00082 unsigned char* seed;
00083 int seed_len;
00084 int *counter;
00085 unsigned long *h;
00086 BN_GENCB *cb;
00087 int result;
00088 };
00089
00090 static void *
00091 dsa_blocking_gen(void *arg)
00092 {
00093 struct dsa_blocking_gen_arg *gen = (struct dsa_blocking_gen_arg *)arg;
00094 gen->result = DSA_generate_parameters_ex(gen->dsa, gen->size, gen->seed, gen->seed_len, gen->counter, gen->h, gen->cb);
00095 return 0;
00096 }
00097 #endif
00098
00099 static DSA *
00100 dsa_generate(int size)
00101 {
00102 #if defined(HAVE_DSA_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB
00103 BN_GENCB cb;
00104 struct ossl_generate_cb_arg cb_arg;
00105 struct dsa_blocking_gen_arg gen_arg;
00106 DSA *dsa = DSA_new();
00107 unsigned char seed[20];
00108 int seed_len = 20, counter;
00109 unsigned long h;
00110
00111 if (!dsa) return 0;
00112 if (!RAND_bytes(seed, seed_len)) {
00113 DSA_free(dsa);
00114 return 0;
00115 }
00116
00117 memset(&cb_arg, 0, sizeof(struct ossl_generate_cb_arg));
00118 if (rb_block_given_p())
00119 cb_arg.yield = 1;
00120 BN_GENCB_set(&cb, ossl_generate_cb_2, &cb_arg);
00121 gen_arg.dsa = dsa;
00122 gen_arg.size = size;
00123 gen_arg.seed = seed;
00124 gen_arg.seed_len = seed_len;
00125 gen_arg.counter = &counter;
00126 gen_arg.h = &h;
00127 gen_arg.cb = &cb;
00128 if (cb_arg.yield == 1) {
00129
00130 dsa_blocking_gen(&gen_arg);
00131 } else {
00132
00133 rb_thread_call_without_gvl(dsa_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg);
00134 }
00135 if (!gen_arg.result) {
00136 DSA_free(dsa);
00137 if (cb_arg.state) rb_jump_tag(cb_arg.state);
00138 return 0;
00139 }
00140 #else
00141 DSA *dsa;
00142 unsigned char seed[20];
00143 int seed_len = 20, counter;
00144 unsigned long h;
00145
00146 if (!RAND_bytes(seed, seed_len)) {
00147 return 0;
00148 }
00149 dsa = DSA_generate_parameters(size, seed, seed_len, &counter, &h,
00150 rb_block_given_p() ? ossl_generate_cb : NULL, NULL);
00151 if(!dsa) return 0;
00152 #endif
00153
00154 if (!DSA_generate_key(dsa)) {
00155 DSA_free(dsa);
00156 return 0;
00157 }
00158
00159 return dsa;
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 static VALUE
00174 ossl_dsa_s_generate(VALUE klass, VALUE size)
00175 {
00176 DSA *dsa = dsa_generate(NUM2INT(size));
00177 VALUE obj = dsa_instance(klass, dsa);
00178
00179 if (obj == Qfalse) {
00180 DSA_free(dsa);
00181 ossl_raise(eDSAError, NULL);
00182 }
00183
00184 return obj;
00185 }
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 static VALUE
00206 ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
00207 {
00208 EVP_PKEY *pkey;
00209 DSA *dsa;
00210 BIO *in;
00211 char *passwd = NULL;
00212 VALUE arg, pass;
00213
00214 GetPKey(self, pkey);
00215 if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
00216 dsa = DSA_new();
00217 }
00218 else if (FIXNUM_P(arg)) {
00219 if (!(dsa = dsa_generate(FIX2INT(arg)))) {
00220 ossl_raise(eDSAError, NULL);
00221 }
00222 }
00223 else {
00224 if (!NIL_P(pass)) passwd = StringValuePtr(pass);
00225 arg = ossl_to_der_if_possible(arg);
00226 in = ossl_obj2bio(arg);
00227 dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
00228 if (!dsa) {
00229 OSSL_BIO_reset(in);
00230 dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL);
00231 }
00232 if (!dsa) {
00233 OSSL_BIO_reset(in);
00234 dsa = d2i_DSAPrivateKey_bio(in, NULL);
00235 }
00236 if (!dsa) {
00237 OSSL_BIO_reset(in);
00238 dsa = d2i_DSA_PUBKEY_bio(in, NULL);
00239 }
00240 if (!dsa) {
00241 OSSL_BIO_reset(in);
00242 dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL);
00243 }
00244 BIO_free(in);
00245 if (!dsa) {
00246 ERR_clear_error();
00247 ossl_raise(eDSAError, "Neither PUB key nor PRIV key");
00248 }
00249 }
00250 if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
00251 DSA_free(dsa);
00252 ossl_raise(eDSAError, NULL);
00253 }
00254
00255 return self;
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265 static VALUE
00266 ossl_dsa_is_public(VALUE self)
00267 {
00268 EVP_PKEY *pkey;
00269
00270 GetPKeyDSA(self, pkey);
00271
00272 return (pkey->pkey.dsa->pub_key) ? Qtrue : Qfalse;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282 static VALUE
00283 ossl_dsa_is_private(VALUE self)
00284 {
00285 EVP_PKEY *pkey;
00286
00287 GetPKeyDSA(self, pkey);
00288
00289 return (DSA_PRIVATE(self, pkey->pkey.dsa)) ? Qtrue : Qfalse;
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 static VALUE
00308 ossl_dsa_export(int argc, VALUE *argv, VALUE self)
00309 {
00310 EVP_PKEY *pkey;
00311 BIO *out;
00312 const EVP_CIPHER *ciph = NULL;
00313 char *passwd = NULL;
00314 VALUE cipher, pass, str;
00315
00316 GetPKeyDSA(self, pkey);
00317 rb_scan_args(argc, argv, "02", &cipher, &pass);
00318 if (!NIL_P(cipher)) {
00319 ciph = GetCipherPtr(cipher);
00320 if (!NIL_P(pass)) {
00321 StringValue(pass);
00322 if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN)
00323 ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long");
00324 passwd = RSTRING_PTR(pass);
00325 }
00326 }
00327 if (!(out = BIO_new(BIO_s_mem()))) {
00328 ossl_raise(eDSAError, NULL);
00329 }
00330 if (DSA_HAS_PRIVATE(pkey->pkey.dsa)) {
00331 if (!PEM_write_bio_DSAPrivateKey(out, pkey->pkey.dsa, ciph,
00332 NULL, 0, ossl_pem_passwd_cb, passwd)){
00333 BIO_free(out);
00334 ossl_raise(eDSAError, NULL);
00335 }
00336 } else {
00337 if (!PEM_write_bio_DSA_PUBKEY(out, pkey->pkey.dsa)) {
00338 BIO_free(out);
00339 ossl_raise(eDSAError, NULL);
00340 }
00341 }
00342 str = ossl_membio2str(out);
00343
00344 return str;
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354 static VALUE
00355 ossl_dsa_to_der(VALUE self)
00356 {
00357 EVP_PKEY *pkey;
00358 int (*i2d_func)_((DSA*, unsigned char**));
00359 unsigned char *p;
00360 long len;
00361 VALUE str;
00362
00363 GetPKeyDSA(self, pkey);
00364 if(DSA_HAS_PRIVATE(pkey->pkey.dsa))
00365 i2d_func = (int(*)_((DSA*,unsigned char**)))i2d_DSAPrivateKey;
00366 else
00367 i2d_func = i2d_DSA_PUBKEY;
00368 if((len = i2d_func(pkey->pkey.dsa, NULL)) <= 0)
00369 ossl_raise(eDSAError, NULL);
00370 str = rb_str_new(0, len);
00371 p = (unsigned char *)RSTRING_PTR(str);
00372 if(i2d_func(pkey->pkey.dsa, &p) < 0)
00373 ossl_raise(eDSAError, NULL);
00374 ossl_str_adjust(str, p);
00375
00376 return str;
00377 }
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 static VALUE
00388 ossl_dsa_get_params(VALUE self)
00389 {
00390 EVP_PKEY *pkey;
00391 VALUE hash;
00392
00393 GetPKeyDSA(self, pkey);
00394
00395 hash = rb_hash_new();
00396
00397 rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dsa->p));
00398 rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(pkey->pkey.dsa->q));
00399 rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dsa->g));
00400 rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dsa->pub_key));
00401 rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dsa->priv_key));
00402
00403 return hash;
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 static VALUE
00415 ossl_dsa_to_text(VALUE self)
00416 {
00417 EVP_PKEY *pkey;
00418 BIO *out;
00419 VALUE str;
00420
00421 GetPKeyDSA(self, pkey);
00422 if (!(out = BIO_new(BIO_s_mem()))) {
00423 ossl_raise(eDSAError, NULL);
00424 }
00425 if (!DSA_print(out, pkey->pkey.dsa, 0)) {
00426 BIO_free(out);
00427 ossl_raise(eDSAError, NULL);
00428 }
00429 str = ossl_membio2str(out);
00430
00431 return str;
00432 }
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 static VALUE
00452 ossl_dsa_to_public_key(VALUE self)
00453 {
00454 EVP_PKEY *pkey;
00455 DSA *dsa;
00456 VALUE obj;
00457
00458 GetPKeyDSA(self, pkey);
00459
00460 dsa = DSAPublicKey_dup(pkey->pkey.dsa);
00461 obj = dsa_instance(CLASS_OF(self), dsa);
00462 if (obj == Qfalse) {
00463 DSA_free(dsa);
00464 ossl_raise(eDSAError, NULL);
00465 }
00466 return obj;
00467 }
00468
00469 #define ossl_dsa_buf_size(pkey) (DSA_size((pkey)->pkey.dsa)+16)
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 static VALUE
00491 ossl_dsa_sign(VALUE self, VALUE data)
00492 {
00493 EVP_PKEY *pkey;
00494 unsigned int buf_len;
00495 VALUE str;
00496
00497 GetPKeyDSA(self, pkey);
00498 StringValue(data);
00499 if (!DSA_PRIVATE(self, pkey->pkey.dsa)) {
00500 ossl_raise(eDSAError, "Private DSA key needed!");
00501 }
00502 str = rb_str_new(0, ossl_dsa_buf_size(pkey));
00503 if (!DSA_sign(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
00504 (unsigned char *)RSTRING_PTR(str),
00505 &buf_len, pkey->pkey.dsa)) {
00506 ossl_raise(eDSAError, NULL);
00507 }
00508 rb_str_set_len(str, buf_len);
00509
00510 return str;
00511 }
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532 static VALUE
00533 ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
00534 {
00535 EVP_PKEY *pkey;
00536 int ret;
00537
00538 GetPKeyDSA(self, pkey);
00539 StringValue(digest);
00540 StringValue(sig);
00541
00542 ret = DSA_verify(0, (unsigned char *)RSTRING_PTR(digest), RSTRING_LENINT(digest),
00543 (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), pkey->pkey.dsa);
00544 if (ret < 0) {
00545 ossl_raise(eDSAError, NULL);
00546 }
00547 else if (ret == 1) {
00548 return Qtrue;
00549 }
00550
00551 return Qfalse;
00552 }
00553
00554 OSSL_PKEY_BN(dsa, p)
00555 OSSL_PKEY_BN(dsa, q)
00556 OSSL_PKEY_BN(dsa, g)
00557 OSSL_PKEY_BN(dsa, pub_key)
00558 OSSL_PKEY_BN(dsa, priv_key)
00559
00560
00561
00562
00563 void
00564 Init_ossl_dsa()
00565 {
00566 #if 0
00567 mOSSL = rb_define_module("OpenSSL");
00568 mPKey = rb_define_module_under(mOSSL, "PKey");
00569 #endif
00570
00571
00572
00573
00574
00575
00576
00577 eDSAError = rb_define_class_under(mPKey, "DSAError", ePKeyError);
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 cDSA = rb_define_class_under(mPKey, "DSA", cPKey);
00592
00593 rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1);
00594 rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1);
00595
00596 rb_define_method(cDSA, "public?", ossl_dsa_is_public, 0);
00597 rb_define_method(cDSA, "private?", ossl_dsa_is_private, 0);
00598 rb_define_method(cDSA, "to_text", ossl_dsa_to_text, 0);
00599 rb_define_method(cDSA, "export", ossl_dsa_export, -1);
00600 rb_define_alias(cDSA, "to_pem", "export");
00601 rb_define_alias(cDSA, "to_s", "export");
00602 rb_define_method(cDSA, "to_der", ossl_dsa_to_der, 0);
00603 rb_define_method(cDSA, "public_key", ossl_dsa_to_public_key, 0);
00604 rb_define_method(cDSA, "syssign", ossl_dsa_sign, 1);
00605 rb_define_method(cDSA, "sysverify", ossl_dsa_verify, 2);
00606
00607 DEF_OSSL_PKEY_BN(cDSA, dsa, p);
00608 DEF_OSSL_PKEY_BN(cDSA, dsa, q);
00609 DEF_OSSL_PKEY_BN(cDSA, dsa, g);
00610 DEF_OSSL_PKEY_BN(cDSA, dsa, pub_key);
00611 DEF_OSSL_PKEY_BN(cDSA, dsa, priv_key);
00612
00613 rb_define_method(cDSA, "params", ossl_dsa_get_params, 0);
00614 }
00615
00616 #else
00617 void
00618 Init_ossl_dsa()
00619 {
00620 }
00621 #endif
00622