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