00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "ossl.h"
00012
00013
00014
00015
00016 VALUE mPKey;
00017 VALUE cPKey;
00018 VALUE ePKeyError;
00019 ID id_private_q;
00020
00021
00022
00023
00024 void
00025 ossl_generate_cb(int p, int n, void *arg)
00026 {
00027 VALUE ary;
00028
00029 ary = rb_ary_new2(2);
00030 rb_ary_store(ary, 0, INT2NUM(p));
00031 rb_ary_store(ary, 1, INT2NUM(n));
00032
00033 rb_yield(ary);
00034 }
00035
00036 #if HAVE_BN_GENCB
00037
00038 int
00039 ossl_generate_cb_2(int p, int n, BN_GENCB *cb)
00040 {
00041 VALUE ary;
00042 struct ossl_generate_cb_arg *arg;
00043 int state;
00044
00045 arg = (struct ossl_generate_cb_arg *)cb->arg;
00046 if (arg->yield) {
00047 ary = rb_ary_new2(2);
00048 rb_ary_store(ary, 0, INT2NUM(p));
00049 rb_ary_store(ary, 1, INT2NUM(n));
00050
00051
00052
00053
00054 rb_protect(rb_yield, ary, &state);
00055 if (state) {
00056 arg->stop = 1;
00057 arg->state = state;
00058 }
00059 }
00060 if (arg->stop) return 0;
00061 return 1;
00062 }
00063
00064 void
00065 ossl_generate_cb_stop(void *ptr)
00066 {
00067 struct ossl_generate_cb_arg *arg = (struct ossl_generate_cb_arg *)ptr;
00068 arg->stop = 1;
00069 }
00070 #endif
00071
00072
00073
00074
00075 VALUE
00076 ossl_pkey_new(EVP_PKEY *pkey)
00077 {
00078 if (!pkey) {
00079 ossl_raise(ePKeyError, "Cannot make new key from NULL.");
00080 }
00081 switch (EVP_PKEY_type(pkey->type)) {
00082 #if !defined(OPENSSL_NO_RSA)
00083 case EVP_PKEY_RSA:
00084 return ossl_rsa_new(pkey);
00085 #endif
00086 #if !defined(OPENSSL_NO_DSA)
00087 case EVP_PKEY_DSA:
00088 return ossl_dsa_new(pkey);
00089 #endif
00090 #if !defined(OPENSSL_NO_DH)
00091 case EVP_PKEY_DH:
00092 return ossl_dh_new(pkey);
00093 #endif
00094 #if !defined(OPENSSL_NO_EC) && (OPENSSL_VERSION_NUMBER >= 0x0090802fL)
00095 case EVP_PKEY_EC:
00096 return ossl_ec_new(pkey);
00097 #endif
00098 default:
00099 ossl_raise(ePKeyError, "unsupported key type");
00100 }
00101
00102 UNREACHABLE;
00103 }
00104
00105 VALUE
00106 ossl_pkey_new_from_file(VALUE filename)
00107 {
00108 FILE *fp;
00109 EVP_PKEY *pkey;
00110
00111 SafeStringValue(filename);
00112 if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
00113 ossl_raise(ePKeyError, "%s", strerror(errno));
00114 }
00115 rb_fd_fix_cloexec(fileno(fp));
00116
00117 pkey = PEM_read_PrivateKey(fp, NULL, ossl_pem_passwd_cb, NULL);
00118 fclose(fp);
00119 if (!pkey) {
00120 ossl_raise(ePKeyError, NULL);
00121 }
00122
00123 return ossl_pkey_new(pkey);
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 static VALUE
00140 ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
00141 {
00142 EVP_PKEY *pkey;
00143 BIO *bio;
00144 VALUE data, pass;
00145 char *passwd = NULL;
00146
00147 rb_scan_args(argc, argv, "11", &data, &pass);
00148
00149 bio = ossl_obj2bio(data);
00150 if (!(pkey = d2i_PrivateKey_bio(bio, NULL))) {
00151 OSSL_BIO_reset(bio);
00152 if (!NIL_P(pass)) {
00153 passwd = StringValuePtr(pass);
00154 }
00155 if (!(pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, passwd))) {
00156 OSSL_BIO_reset(bio);
00157 if (!(pkey = d2i_PUBKEY_bio(bio, NULL))) {
00158 OSSL_BIO_reset(bio);
00159 if (!NIL_P(pass)) {
00160 passwd = StringValuePtr(pass);
00161 }
00162 pkey = PEM_read_bio_PUBKEY(bio, NULL, ossl_pem_passwd_cb, passwd);
00163 }
00164 }
00165 }
00166
00167 BIO_free(bio);
00168 if (!pkey)
00169 ossl_raise(rb_eArgError, "Could not parse PKey");
00170 return ossl_pkey_new(pkey);
00171 }
00172
00173 EVP_PKEY *
00174 GetPKeyPtr(VALUE obj)
00175 {
00176 EVP_PKEY *pkey;
00177
00178 SafeGetPKey(obj, pkey);
00179
00180 return pkey;
00181 }
00182
00183 EVP_PKEY *
00184 GetPrivPKeyPtr(VALUE obj)
00185 {
00186 EVP_PKEY *pkey;
00187
00188 if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) {
00189 ossl_raise(rb_eArgError, "Private key is needed.");
00190 }
00191 SafeGetPKey(obj, pkey);
00192
00193 return pkey;
00194 }
00195
00196 EVP_PKEY *
00197 DupPKeyPtr(VALUE obj)
00198 {
00199 EVP_PKEY *pkey;
00200
00201 SafeGetPKey(obj, pkey);
00202 CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
00203
00204 return pkey;
00205 }
00206
00207 EVP_PKEY *
00208 DupPrivPKeyPtr(VALUE obj)
00209 {
00210 EVP_PKEY *pkey;
00211
00212 if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) {
00213 ossl_raise(rb_eArgError, "Private key is needed.");
00214 }
00215 SafeGetPKey(obj, pkey);
00216 CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
00217
00218 return pkey;
00219 }
00220
00221
00222
00223
00224 static VALUE
00225 ossl_pkey_alloc(VALUE klass)
00226 {
00227 EVP_PKEY *pkey;
00228 VALUE obj;
00229
00230 if (!(pkey = EVP_PKEY_new())) {
00231 ossl_raise(ePKeyError, NULL);
00232 }
00233 WrapPKey(klass, obj, pkey);
00234
00235 return obj;
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245 static VALUE
00246 ossl_pkey_initialize(VALUE self)
00247 {
00248 if (rb_obj_is_instance_of(self, cPKey)) {
00249 ossl_raise(rb_eNotImpError, "OpenSSL::PKey::PKey is an abstract class.");
00250 }
00251 return self;
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 static VALUE
00272 ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
00273 {
00274 EVP_PKEY *pkey;
00275 EVP_MD_CTX ctx;
00276 unsigned int buf_len;
00277 VALUE str;
00278 int result;
00279
00280 if (rb_funcall(self, id_private_q, 0, NULL) != Qtrue) {
00281 ossl_raise(rb_eArgError, "Private key is needed.");
00282 }
00283 GetPKey(self, pkey);
00284 EVP_SignInit(&ctx, GetDigestPtr(digest));
00285 StringValue(data);
00286 EVP_SignUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
00287 str = rb_str_new(0, EVP_PKEY_size(pkey)+16);
00288 result = EVP_SignFinal(&ctx, (unsigned char *)RSTRING_PTR(str), &buf_len, pkey);
00289 EVP_MD_CTX_cleanup(&ctx);
00290 if (!result)
00291 ossl_raise(ePKeyError, NULL);
00292 assert((long)buf_len <= RSTRING_LEN(str));
00293 rb_str_set_len(str, buf_len);
00294
00295 return str;
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 static VALUE
00320 ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
00321 {
00322 EVP_PKEY *pkey;
00323 EVP_MD_CTX ctx;
00324 int result;
00325
00326 GetPKey(self, pkey);
00327 StringValue(sig);
00328 StringValue(data);
00329 EVP_VerifyInit(&ctx, GetDigestPtr(digest));
00330 EVP_VerifyUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
00331 result = EVP_VerifyFinal(&ctx, (unsigned char *)RSTRING_PTR(sig), RSTRING_LENINT(sig), pkey);
00332 EVP_MD_CTX_cleanup(&ctx);
00333 switch (result) {
00334 case 0:
00335 return Qfalse;
00336 case 1:
00337 return Qtrue;
00338 default:
00339 ossl_raise(ePKeyError, NULL);
00340 }
00341 return Qnil;
00342 }
00343
00344
00345
00346
00347 void
00348 Init_ossl_pkey()
00349 {
00350 #if 0
00351 mOSSL = rb_define_module("OpenSSL");
00352 #endif
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 mPKey = rb_define_module_under(mOSSL, "PKey");
00406
00407
00408
00409
00410
00411 ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
00423
00424 rb_define_module_function(mPKey, "read", ossl_pkey_new_from_data, -1);
00425
00426 rb_define_alloc_func(cPKey, ossl_pkey_alloc);
00427 rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
00428
00429 rb_define_method(cPKey, "sign", ossl_pkey_sign, 2);
00430 rb_define_method(cPKey, "verify", ossl_pkey_verify, 3);
00431
00432 id_private_q = rb_intern("private?");
00433
00434
00435
00436
00437 Init_ossl_rsa();
00438 Init_ossl_dsa();
00439 Init_ossl_dh();
00440 Init_ossl_ec();
00441 }
00442
00443