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 static DSA *
00079 dsa_generate(int size)
00080 {
00081 DSA *dsa;
00082 unsigned char seed[20];
00083 int seed_len = 20, counter;
00084 unsigned long h;
00085
00086 if (!RAND_bytes(seed, seed_len)) {
00087 return 0;
00088 }
00089 dsa = DSA_generate_parameters(size, seed, seed_len, &counter, &h,
00090 rb_block_given_p() ? ossl_generate_cb : NULL,
00091 NULL);
00092 if(!dsa) return 0;
00093
00094 if (!DSA_generate_key(dsa)) {
00095 DSA_free(dsa);
00096 return 0;
00097 }
00098
00099 return dsa;
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 static VALUE
00114 ossl_dsa_s_generate(VALUE klass, VALUE size)
00115 {
00116 DSA *dsa = dsa_generate(NUM2INT(size));
00117 VALUE obj = dsa_instance(klass, dsa);
00118
00119 if (obj == Qfalse) {
00120 DSA_free(dsa);
00121 ossl_raise(eDSAError, NULL);
00122 }
00123
00124 return obj;
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 static VALUE
00146 ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
00147 {
00148 EVP_PKEY *pkey;
00149 DSA *dsa;
00150 BIO *in;
00151 char *passwd = NULL;
00152 VALUE arg, pass;
00153
00154 GetPKey(self, pkey);
00155 if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
00156 dsa = DSA_new();
00157 }
00158 else if (FIXNUM_P(arg)) {
00159 if (!(dsa = dsa_generate(FIX2INT(arg)))) {
00160 ossl_raise(eDSAError, NULL);
00161 }
00162 }
00163 else {
00164 if (!NIL_P(pass)) passwd = StringValuePtr(pass);
00165 arg = ossl_to_der_if_possible(arg);
00166 in = ossl_obj2bio(arg);
00167 dsa = PEM_read_bio_DSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
00168 if (!dsa) {
00169 OSSL_BIO_reset(in);
00170 dsa = PEM_read_bio_DSA_PUBKEY(in, NULL, NULL, NULL);
00171 }
00172 if (!dsa) {
00173 OSSL_BIO_reset(in);
00174 dsa = d2i_DSAPrivateKey_bio(in, NULL);
00175 }
00176 if (!dsa) {
00177 OSSL_BIO_reset(in);
00178 dsa = d2i_DSA_PUBKEY_bio(in, NULL);
00179 }
00180 if (!dsa) {
00181 OSSL_BIO_reset(in);
00182 dsa = PEM_read_bio_DSAPublicKey(in, NULL, NULL, NULL);
00183 }
00184 BIO_free(in);
00185 if (!dsa) {
00186 ERR_clear_error();
00187 ossl_raise(eDSAError, "Neither PUB key nor PRIV key:");
00188 }
00189 }
00190 if (!EVP_PKEY_assign_DSA(pkey, dsa)) {
00191 DSA_free(dsa);
00192 ossl_raise(eDSAError, NULL);
00193 }
00194
00195 return self;
00196 }
00197
00198
00199
00200
00201
00202
00203
00204
00205 static VALUE
00206 ossl_dsa_is_public(VALUE self)
00207 {
00208 EVP_PKEY *pkey;
00209
00210 GetPKeyDSA(self, pkey);
00211
00212 return (pkey->pkey.dsa->pub_key) ? Qtrue : Qfalse;
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222 static VALUE
00223 ossl_dsa_is_private(VALUE self)
00224 {
00225 EVP_PKEY *pkey;
00226
00227 GetPKeyDSA(self, pkey);
00228
00229 return (DSA_PRIVATE(self, pkey->pkey.dsa)) ? Qtrue : Qfalse;
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 static VALUE
00248 ossl_dsa_export(int argc, VALUE *argv, VALUE self)
00249 {
00250 EVP_PKEY *pkey;
00251 BIO *out;
00252 const EVP_CIPHER *ciph = NULL;
00253 char *passwd = NULL;
00254 VALUE cipher, pass, str;
00255
00256 GetPKeyDSA(self, pkey);
00257 rb_scan_args(argc, argv, "02", &cipher, &pass);
00258 if (!NIL_P(cipher)) {
00259 ciph = GetCipherPtr(cipher);
00260 if (!NIL_P(pass)) {
00261 passwd = StringValuePtr(pass);
00262 }
00263 }
00264 if (!(out = BIO_new(BIO_s_mem()))) {
00265 ossl_raise(eDSAError, NULL);
00266 }
00267 if (DSA_HAS_PRIVATE(pkey->pkey.dsa)) {
00268 if (!PEM_write_bio_DSAPrivateKey(out, pkey->pkey.dsa, ciph,
00269 NULL, 0, ossl_pem_passwd_cb, passwd)){
00270 BIO_free(out);
00271 ossl_raise(eDSAError, NULL);
00272 }
00273 } else {
00274 if (!PEM_write_bio_DSA_PUBKEY(out, pkey->pkey.dsa)) {
00275 BIO_free(out);
00276 ossl_raise(eDSAError, NULL);
00277 }
00278 }
00279 str = ossl_membio2str(out);
00280
00281 return str;
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291 static VALUE
00292 ossl_dsa_to_der(VALUE self)
00293 {
00294 EVP_PKEY *pkey;
00295 int (*i2d_func)_((DSA*, unsigned char**));
00296 unsigned char *p;
00297 long len;
00298 VALUE str;
00299
00300 GetPKeyDSA(self, pkey);
00301 if(DSA_HAS_PRIVATE(pkey->pkey.dsa))
00302 i2d_func = (int(*)_((DSA*,unsigned char**)))i2d_DSAPrivateKey;
00303 else
00304 i2d_func = i2d_DSA_PUBKEY;
00305 if((len = i2d_func(pkey->pkey.dsa, NULL)) <= 0)
00306 ossl_raise(eDSAError, NULL);
00307 str = rb_str_new(0, len);
00308 p = (unsigned char *)RSTRING_PTR(str);
00309 if(i2d_func(pkey->pkey.dsa, &p) < 0)
00310 ossl_raise(eDSAError, NULL);
00311 ossl_str_adjust(str, p);
00312
00313 return str;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 static VALUE
00325 ossl_dsa_get_params(VALUE self)
00326 {
00327 EVP_PKEY *pkey;
00328 VALUE hash;
00329
00330 GetPKeyDSA(self, pkey);
00331
00332 hash = rb_hash_new();
00333
00334 rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.dsa->p));
00335 rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(pkey->pkey.dsa->q));
00336 rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(pkey->pkey.dsa->g));
00337 rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pkey->pkey.dsa->pub_key));
00338 rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(pkey->pkey.dsa->priv_key));
00339
00340 return hash;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 static VALUE
00352 ossl_dsa_to_text(VALUE self)
00353 {
00354 EVP_PKEY *pkey;
00355 BIO *out;
00356 VALUE str;
00357
00358 GetPKeyDSA(self, pkey);
00359 if (!(out = BIO_new(BIO_s_mem()))) {
00360 ossl_raise(eDSAError, NULL);
00361 }
00362 if (!DSA_print(out, pkey->pkey.dsa, 0)) {
00363 BIO_free(out);
00364 ossl_raise(eDSAError, NULL);
00365 }
00366 str = ossl_membio2str(out);
00367
00368 return str;
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 static VALUE
00389 ossl_dsa_to_public_key(VALUE self)
00390 {
00391 EVP_PKEY *pkey;
00392 DSA *dsa;
00393 VALUE obj;
00394
00395 GetPKeyDSA(self, pkey);
00396
00397 dsa = DSAPublicKey_dup(pkey->pkey.dsa);
00398 obj = dsa_instance(CLASS_OF(self), dsa);
00399 if (obj == Qfalse) {
00400 DSA_free(dsa);
00401 ossl_raise(eDSAError, NULL);
00402 }
00403 return obj;
00404 }
00405
00406 #define ossl_dsa_buf_size(pkey) (DSA_size((pkey)->pkey.dsa)+16)
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 static VALUE
00428 ossl_dsa_sign(VALUE self, VALUE data)
00429 {
00430 EVP_PKEY *pkey;
00431 unsigned int buf_len;
00432 VALUE str;
00433
00434 GetPKeyDSA(self, pkey);
00435 StringValue(data);
00436 if (!DSA_PRIVATE(self, pkey->pkey.dsa)) {
00437 ossl_raise(eDSAError, "Private DSA key needed!");
00438 }
00439 str = rb_str_new(0, ossl_dsa_buf_size(pkey));
00440 if (!DSA_sign(0, (unsigned char *)RSTRING_PTR(data), RSTRING_LENINT(data),
00441 (unsigned char *)RSTRING_PTR(str),
00442 &buf_len, pkey->pkey.dsa)) {
00443 ossl_raise(eDSAError, NULL);
00444 }
00445 rb_str_set_len(str, buf_len);
00446
00447 return str;
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 static VALUE
00470 ossl_dsa_verify(VALUE self, VALUE digest, VALUE sig)
00471 {
00472 EVP_PKEY *pkey;
00473 int ret;
00474
00475 GetPKeyDSA(self, pkey);
00476 StringValue(digest);
00477 StringValue(sig);
00478
00479 ret = DSA_verify(0, (unsigned char *)RSTRING_PTR(digest), RSTRING_LENINT(digest),
00480 (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), pkey->pkey.dsa);
00481 if (ret < 0) {
00482 ossl_raise(eDSAError, NULL);
00483 }
00484 else if (ret == 1) {
00485 return Qtrue;
00486 }
00487
00488 return Qfalse;
00489 }
00490
00491 OSSL_PKEY_BN(dsa, p)
00492 OSSL_PKEY_BN(dsa, q)
00493 OSSL_PKEY_BN(dsa, g)
00494 OSSL_PKEY_BN(dsa, pub_key)
00495 OSSL_PKEY_BN(dsa, priv_key)
00496
00497
00498
00499
00500 void
00501 Init_ossl_dsa()
00502 {
00503 #if 0
00504 mOSSL = rb_define_module("OpenSSL");
00505 mPKey = rb_define_module_under(mOSSL, "PKey");
00506 #endif
00507
00508
00509
00510
00511
00512
00513
00514 eDSAError = rb_define_class_under(mPKey, "DSAError", ePKeyError);
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528 cDSA = rb_define_class_under(mPKey, "DSA", cPKey);
00529
00530 rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1);
00531 rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1);
00532
00533 rb_define_method(cDSA, "public?", ossl_dsa_is_public, 0);
00534 rb_define_method(cDSA, "private?", ossl_dsa_is_private, 0);
00535 rb_define_method(cDSA, "to_text", ossl_dsa_to_text, 0);
00536 rb_define_method(cDSA, "export", ossl_dsa_export, -1);
00537 rb_define_alias(cDSA, "to_pem", "export");
00538 rb_define_alias(cDSA, "to_s", "export");
00539 rb_define_method(cDSA, "to_der", ossl_dsa_to_der, 0);
00540 rb_define_method(cDSA, "public_key", ossl_dsa_to_public_key, 0);
00541 rb_define_method(cDSA, "syssign", ossl_dsa_sign, 1);
00542 rb_define_method(cDSA, "sysverify", ossl_dsa_verify, 2);
00543
00544 DEF_OSSL_PKEY_BN(cDSA, dsa, p);
00545 DEF_OSSL_PKEY_BN(cDSA, dsa, q);
00546 DEF_OSSL_PKEY_BN(cDSA, dsa, g);
00547 DEF_OSSL_PKEY_BN(cDSA, dsa, pub_key);
00548 DEF_OSSL_PKEY_BN(cDSA, dsa, priv_key);
00549
00550 rb_define_method(cDSA, "params", ossl_dsa_get_params, 0);
00551 }
00552
00553 #else
00554 void
00555 Init_ossl_dsa()
00556 {
00557 }
00558 #endif
00559