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