• Main Page
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

ext/openssl/ossl_pkey_rsa.c

Go to the documentation of this file.
00001 /*
00002  * $Id: ossl_pkey_rsa.c 31795 2011-05-29 22:49:02Z yugui $
00003  * 'OpenSSL for Ruby' project
00004  * Copyright (C) 2001-2002  Michal Rokos <m.rokos@sh.cvut.cz>
00005  * All rights reserved.
00006  */
00007 /*
00008  * This program is licenced under the same licence as Ruby.
00009  * (See the file 'LICENCE'.)
00010  */
00011 #if !defined(OPENSSL_NO_RSA)
00012 
00013 #include "ossl.h"
00014 
00015 #define GetPKeyRSA(obj, pkey) do { \
00016     GetPKey(obj, pkey); \
00017     if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) { /* PARANOIA? */ \
00018         ossl_raise(rb_eRuntimeError, "THIS IS NOT A RSA!") ; \
00019     } \
00020 } while (0)
00021 
00022 #define RSA_HAS_PRIVATE(rsa) ((rsa)->p && (rsa)->q)
00023 #define RSA_PRIVATE(obj,rsa) (RSA_HAS_PRIVATE(rsa)||OSSL_PKEY_IS_PRIVATE(obj))
00024 
00025 /*
00026  * Classes
00027  */
00028 VALUE cRSA;
00029 VALUE eRSAError;
00030 
00031 /*
00032  * Public
00033  */
00034 static VALUE
00035 rsa_instance(VALUE klass, RSA *rsa)
00036 {
00037     EVP_PKEY *pkey;
00038     VALUE obj;
00039 
00040     if (!rsa) {
00041         return Qfalse;
00042     }
00043     if (!(pkey = EVP_PKEY_new())) {
00044         return Qfalse;
00045     }
00046     if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
00047         EVP_PKEY_free(pkey);
00048         return Qfalse;
00049     }
00050     WrapPKey(klass, obj, pkey);
00051 
00052     return obj;
00053 }
00054 
00055 VALUE
00056 ossl_rsa_new(EVP_PKEY *pkey)
00057 {
00058     VALUE obj;
00059 
00060     if (!pkey) {
00061         obj = rsa_instance(cRSA, RSA_new());
00062     }
00063     else {
00064         if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) {
00065             ossl_raise(rb_eTypeError, "Not a RSA key!");
00066         }
00067         WrapPKey(cRSA, obj, pkey);
00068     }
00069     if (obj == Qfalse) {
00070         ossl_raise(eRSAError, NULL);
00071     }
00072 
00073     return obj;
00074 }
00075 
00076 /*
00077  * Private
00078  */
00079 static RSA *
00080 rsa_generate(int size, int exp)
00081 {
00082     return RSA_generate_key(size, exp,
00083             rb_block_given_p() ? ossl_generate_cb : NULL,
00084             NULL);
00085 }
00086 
00087 /*
00088  *  call-seq:
00089  *     RSA.generate(size [, exponent]) -> rsa
00090  *
00091  *  === Parameters
00092  *  * +size+ is an integer representing the desired key size.  Keys smaller than 1024 should be considered insecure.
00093  *  * +exponent+ is an odd number normally 3, 17, or 65537.
00094  *
00095  */
00096 static VALUE
00097 ossl_rsa_s_generate(int argc, VALUE *argv, VALUE klass)
00098 {
00099 /* why does this method exist?  why can't initialize take an optional exponent? */
00100     RSA *rsa;
00101     VALUE size, exp;
00102     VALUE obj;
00103 
00104     rb_scan_args(argc, argv, "11", &size, &exp);
00105 
00106     rsa = rsa_generate(NUM2INT(size), NIL_P(exp) ? RSA_F4 : NUM2INT(exp)); /* err handled by rsa_instance */
00107     obj = rsa_instance(klass, rsa);
00108 
00109     if (obj == Qfalse) {
00110         RSA_free(rsa);
00111         ossl_raise(eRSAError, NULL);
00112     }
00113 
00114     return obj;
00115 }
00116 
00117 /*
00118  *  call-seq:
00119  *     RSA.new([size | encoded_key] [, pass]) -> rsa
00120  *
00121  *  === Parameters
00122  *  * +size+ is an integer representing the desired key size.
00123  *  * +encoded_key+ is a string containing PEM or DER encoded key.
00124  *  * +pass+ is an optional string with the password to decrypt the encoded key.
00125  *
00126  *  === Examples
00127  *  * RSA.new(2048) -> rsa
00128  *  * RSA.new(File.read("rsa.pem")) -> rsa
00129  *  * RSA.new(File.read("rsa.pem"), "mypassword") -> rsa
00130  */
00131 static VALUE
00132 ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
00133 {
00134     EVP_PKEY *pkey;
00135     RSA *rsa;
00136     BIO *in;
00137     char *passwd = NULL;
00138     VALUE arg, pass;
00139 
00140     GetPKey(self, pkey);
00141     if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) {
00142         rsa = RSA_new();
00143     }
00144     else if (FIXNUM_P(arg)) {
00145         rsa = rsa_generate(FIX2INT(arg), NIL_P(pass) ? RSA_F4 : NUM2INT(pass));
00146         if (!rsa) ossl_raise(eRSAError, NULL);
00147     }
00148     else {
00149         if (!NIL_P(pass)) passwd = StringValuePtr(pass);
00150         arg = ossl_to_der_if_possible(arg);
00151         in = ossl_obj2bio(arg);
00152         rsa = PEM_read_bio_RSAPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
00153         if (!rsa) {
00154             (void)BIO_reset(in);
00155             (void)ERR_get_error();
00156             rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL);
00157         }
00158         if (!rsa) {
00159             (void)BIO_reset(in);
00160             (void)ERR_get_error();
00161             rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL);
00162         }
00163         if (!rsa) {
00164             (void)BIO_reset(in);
00165             (void)ERR_get_error();
00166             rsa = d2i_RSAPrivateKey_bio(in, NULL);
00167         }
00168         if (!rsa) {
00169             (void)BIO_reset(in);
00170             (void)ERR_get_error();
00171             rsa = d2i_RSAPublicKey_bio(in, NULL);
00172         }
00173         if (!rsa) {
00174             (void)BIO_reset(in);
00175             (void)ERR_get_error();
00176             rsa = d2i_RSA_PUBKEY_bio(in, NULL);
00177         }
00178         BIO_free(in);
00179         if (!rsa) {
00180             (void)ERR_get_error();
00181             ossl_raise(eRSAError, "Neither PUB key nor PRIV key:");
00182         }
00183     }
00184     if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
00185         RSA_free(rsa);
00186         ossl_raise(eRSAError, NULL);
00187     }
00188 
00189     return self;
00190 }
00191 
00192 /*
00193  *  call-seq:
00194  *     rsa.public? -> true
00195  *
00196  *  The return value is always true since every private key is also a public key.
00197  *
00198  */
00199 static VALUE
00200 ossl_rsa_is_public(VALUE self)
00201 {
00202     EVP_PKEY *pkey;
00203 
00204     GetPKeyRSA(self, pkey);
00205     /*
00206      * This method should check for n and e.  BUG.
00207      */
00208     return Qtrue;
00209 }
00210 
00211 /*
00212  *  call-seq:
00213  *     rsa.private? -> true | false
00214  *
00215  */
00216 static VALUE
00217 ossl_rsa_is_private(VALUE self)
00218 {
00219     EVP_PKEY *pkey;
00220 
00221     GetPKeyRSA(self, pkey);
00222 
00223     return (RSA_PRIVATE(self, pkey->pkey.rsa)) ? Qtrue : Qfalse;
00224 }
00225 
00226 /*
00227  *  call-seq:
00228  *     rsa.to_pem([cipher, pass]) -> aString
00229  *
00230  *  === Parameters
00231  *  * +cipher+ is a Cipher object.
00232  *  * +pass+ is a string.
00233  *
00234  *  === Examples
00235  *  * rsa.to_pem -> aString
00236  *  * rsa.to_pem(cipher, pass) -> aString
00237  */
00238 static VALUE
00239 ossl_rsa_export(int argc, VALUE *argv, VALUE self)
00240 {
00241     EVP_PKEY *pkey;
00242     BIO *out;
00243     const EVP_CIPHER *ciph = NULL;
00244     char *passwd = NULL;
00245     VALUE cipher, pass, str;
00246 
00247     GetPKeyRSA(self, pkey);
00248 
00249     rb_scan_args(argc, argv, "02", &cipher, &pass);
00250 
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(eRSAError, NULL);
00259     }
00260     if (RSA_HAS_PRIVATE(pkey->pkey.rsa)) {
00261         if (!PEM_write_bio_RSAPrivateKey(out, pkey->pkey.rsa, ciph,
00262                                          NULL, 0, ossl_pem_passwd_cb, passwd)) {
00263             BIO_free(out);
00264             ossl_raise(eRSAError, NULL);
00265         }
00266     } else {
00267         if (!PEM_write_bio_RSAPublicKey(out, pkey->pkey.rsa)) {
00268             BIO_free(out);
00269             ossl_raise(eRSAError, NULL);
00270         }
00271     }
00272     str = ossl_membio2str(out);
00273 
00274     return str;
00275 }
00276 
00277 /*
00278  *  call-seq:
00279  *     rsa.to_der -> aString
00280  *
00281  */
00282 static VALUE
00283 ossl_rsa_to_der(VALUE self)
00284 {
00285     EVP_PKEY *pkey;
00286     int (*i2d_func)_((const RSA*, unsigned char**));
00287     unsigned char *p;
00288     long len;
00289     VALUE str;
00290 
00291     GetPKeyRSA(self, pkey);
00292     if(RSA_HAS_PRIVATE(pkey->pkey.rsa))
00293         i2d_func = i2d_RSAPrivateKey;
00294     else
00295         i2d_func = i2d_RSAPublicKey;
00296     if((len = i2d_func(pkey->pkey.rsa, NULL)) <= 0)
00297         ossl_raise(eRSAError, NULL);
00298     str = rb_str_new(0, len);
00299     p = (unsigned char *)RSTRING_PTR(str);
00300     if(i2d_func(pkey->pkey.rsa, &p) < 0)
00301         ossl_raise(eRSAError, NULL);
00302     ossl_str_adjust(str, p);
00303 
00304     return str;
00305 }
00306 
00307 #define ossl_rsa_buf_size(pkey) (RSA_size((pkey)->pkey.rsa)+16)
00308 
00309 /*
00310  *  call-seq:
00311  *     rsa.public_encrypt(string [, padding]) -> aString
00312  *
00313  */
00314 static VALUE
00315 ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
00316 {
00317     EVP_PKEY *pkey;
00318     int buf_len, pad;
00319     VALUE str, buffer, padding;
00320 
00321     GetPKeyRSA(self, pkey);
00322     rb_scan_args(argc, argv, "11", &buffer, &padding);
00323     pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
00324     StringValue(buffer);
00325     str = rb_str_new(0, ossl_rsa_buf_size(pkey));
00326     buf_len = RSA_public_encrypt(RSTRING_LEN(buffer), (unsigned char *)RSTRING_PTR(buffer),
00327                                  (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa,
00328                                  pad);
00329     if (buf_len < 0) ossl_raise(eRSAError, NULL);
00330     rb_str_set_len(str, buf_len);
00331 
00332     return str;
00333 }
00334 
00335 /*
00336  *  call-seq:
00337  *     rsa.public_decrypt(string [, padding]) -> aString
00338  *
00339  */
00340 static VALUE
00341 ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
00342 {
00343     EVP_PKEY *pkey;
00344     int buf_len, pad;
00345     VALUE str, buffer, padding;
00346 
00347     GetPKeyRSA(self, pkey);
00348     rb_scan_args(argc, argv, "11", &buffer, &padding);
00349     pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
00350     StringValue(buffer);
00351     str = rb_str_new(0, ossl_rsa_buf_size(pkey));
00352     buf_len = RSA_public_decrypt(RSTRING_LEN(buffer), (unsigned char *)RSTRING_PTR(buffer),
00353                                  (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa,
00354                                  pad);
00355     if (buf_len < 0) ossl_raise(eRSAError, NULL);
00356     rb_str_set_len(str, buf_len);
00357 
00358     return str;
00359 }
00360 
00361 /*
00362  *  call-seq:
00363  *     rsa.private_encrypt(string [, padding]) -> aString
00364  *
00365  */
00366 static VALUE
00367 ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
00368 {
00369     EVP_PKEY *pkey;
00370     int buf_len, pad;
00371     VALUE str, buffer, padding;
00372 
00373     GetPKeyRSA(self, pkey);
00374     if (!RSA_PRIVATE(self, pkey->pkey.rsa)) {
00375         ossl_raise(eRSAError, "private key needed.");
00376     }
00377     rb_scan_args(argc, argv, "11", &buffer, &padding);
00378     pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
00379     StringValue(buffer);
00380     str = rb_str_new(0, ossl_rsa_buf_size(pkey));
00381     buf_len = RSA_private_encrypt(RSTRING_LEN(buffer), (unsigned char *)RSTRING_PTR(buffer),
00382                                   (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa,
00383                                   pad);
00384     if (buf_len < 0) ossl_raise(eRSAError, NULL);
00385     rb_str_set_len(str, buf_len);
00386 
00387     return str;
00388 }
00389 
00390 
00391 /*
00392  *  call-seq:
00393  *     rsa.private_decrypt(string [, padding]) -> aString
00394  *
00395  */
00396 static VALUE
00397 ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
00398 {
00399     EVP_PKEY *pkey;
00400     int buf_len, pad;
00401     VALUE str, buffer, padding;
00402 
00403     GetPKeyRSA(self, pkey);
00404     if (!RSA_PRIVATE(self, pkey->pkey.rsa)) {
00405         ossl_raise(eRSAError, "private key needed.");
00406     }
00407     rb_scan_args(argc, argv, "11", &buffer, &padding);
00408     pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
00409     StringValue(buffer);
00410     str = rb_str_new(0, ossl_rsa_buf_size(pkey));
00411     buf_len = RSA_private_decrypt(RSTRING_LEN(buffer), (unsigned char *)RSTRING_PTR(buffer),
00412                                   (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa,
00413                                   pad);
00414     if (buf_len < 0) ossl_raise(eRSAError, NULL);
00415     rb_str_set_len(str, buf_len);
00416 
00417     return str;
00418 }
00419 
00420 /*
00421  *  call-seq:
00422  *     rsa.params -> hash
00423  *
00424  * Stores all parameters of key to the hash
00425  * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
00426  * Don't use :-)) (I's up to you)
00427  */
00428 static VALUE
00429 ossl_rsa_get_params(VALUE self)
00430 {
00431     EVP_PKEY *pkey;
00432     VALUE hash;
00433 
00434     GetPKeyRSA(self, pkey);
00435 
00436     hash = rb_hash_new();
00437 
00438     rb_hash_aset(hash, rb_str_new2("n"), ossl_bn_new(pkey->pkey.rsa->n));
00439     rb_hash_aset(hash, rb_str_new2("e"), ossl_bn_new(pkey->pkey.rsa->e));
00440     rb_hash_aset(hash, rb_str_new2("d"), ossl_bn_new(pkey->pkey.rsa->d));
00441     rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.rsa->p));
00442     rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(pkey->pkey.rsa->q));
00443     rb_hash_aset(hash, rb_str_new2("dmp1"), ossl_bn_new(pkey->pkey.rsa->dmp1));
00444     rb_hash_aset(hash, rb_str_new2("dmq1"), ossl_bn_new(pkey->pkey.rsa->dmq1));
00445     rb_hash_aset(hash, rb_str_new2("iqmp"), ossl_bn_new(pkey->pkey.rsa->iqmp));
00446 
00447     return hash;
00448 }
00449 
00450 /*
00451  *  call-seq:
00452  *     rsa.to_text -> aString
00453  *
00454  * Prints all parameters of key to buffer
00455  * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
00456  * Don't use :-)) (It's up to you)
00457  */
00458 static VALUE
00459 ossl_rsa_to_text(VALUE self)
00460 {
00461     EVP_PKEY *pkey;
00462     BIO *out;
00463     VALUE str;
00464 
00465     GetPKeyRSA(self, pkey);
00466     if (!(out = BIO_new(BIO_s_mem()))) {
00467         ossl_raise(eRSAError, NULL);
00468     }
00469     if (!RSA_print(out, pkey->pkey.rsa, 0)) { /* offset = 0 */
00470         BIO_free(out);
00471         ossl_raise(eRSAError, NULL);
00472     }
00473     str = ossl_membio2str(out);
00474 
00475     return str;
00476 }
00477 
00478 /*
00479  *  call-seq:
00480  *     rsa.public_key -> aRSA
00481  *
00482  * Makes new instance RSA PUBLIC_KEY from PRIVATE_KEY
00483  */
00484 static VALUE
00485 ossl_rsa_to_public_key(VALUE self)
00486 {
00487     EVP_PKEY *pkey;
00488     RSA *rsa;
00489     VALUE obj;
00490 
00491     GetPKeyRSA(self, pkey);
00492     /* err check performed by rsa_instance */
00493     rsa = RSAPublicKey_dup(pkey->pkey.rsa);
00494     obj = rsa_instance(CLASS_OF(self), rsa);
00495     if (obj == Qfalse) {
00496         RSA_free(rsa);
00497         ossl_raise(eRSAError, NULL);
00498     }
00499     return obj;
00500 }
00501 
00502 /*
00503  * TODO: Test me
00504 
00505 static VALUE
00506 ossl_rsa_blinding_on(VALUE self)
00507 {
00508     EVP_PKEY *pkey;
00509 
00510     GetPKeyRSA(self, pkey);
00511 
00512     if (RSA_blinding_on(pkey->pkey.rsa, ossl_bn_ctx) != 1) {
00513         ossl_raise(eRSAError, NULL);
00514     }
00515     return self;
00516 }
00517 
00518 static VALUE
00519 ossl_rsa_blinding_off(VALUE self)
00520 {
00521     EVP_PKEY *pkey;
00522 
00523     GetPKeyRSA(self, pkey);
00524     RSA_blinding_off(pkey->pkey.rsa);
00525 
00526     return self;
00527 }
00528  */
00529 
00530 OSSL_PKEY_BN(rsa, n)
00531 OSSL_PKEY_BN(rsa, e)
00532 OSSL_PKEY_BN(rsa, d)
00533 OSSL_PKEY_BN(rsa, p)
00534 OSSL_PKEY_BN(rsa, q)
00535 OSSL_PKEY_BN(rsa, dmp1)
00536 OSSL_PKEY_BN(rsa, dmq1)
00537 OSSL_PKEY_BN(rsa, iqmp)
00538 
00539 /*
00540  * INIT
00541  */
00542 #define DefRSAConst(x) rb_define_const(cRSA, #x,INT2FIX(RSA_##x))
00543 
00544 void
00545 Init_ossl_rsa()
00546 {
00547 #if 0 /* let rdoc know about mOSSL and mPKey */
00548     mOSSL = rb_define_module("OpenSSL");
00549     mPKey = rb_define_module_under(mOSSL, "PKey");
00550 #endif
00551 
00552     eRSAError = rb_define_class_under(mPKey, "RSAError", ePKeyError);
00553 
00554     cRSA = rb_define_class_under(mPKey, "RSA", cPKey);
00555 
00556     rb_define_singleton_method(cRSA, "generate", ossl_rsa_s_generate, -1);
00557     rb_define_method(cRSA, "initialize", ossl_rsa_initialize, -1);
00558 
00559     rb_define_method(cRSA, "public?", ossl_rsa_is_public, 0);
00560     rb_define_method(cRSA, "private?", ossl_rsa_is_private, 0);
00561     rb_define_method(cRSA, "to_text", ossl_rsa_to_text, 0);
00562     rb_define_method(cRSA, "export", ossl_rsa_export, -1);
00563     rb_define_alias(cRSA, "to_pem", "export");
00564     rb_define_alias(cRSA, "to_s", "export");
00565     rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0);
00566     rb_define_method(cRSA, "public_key", ossl_rsa_to_public_key, 0);
00567     rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, -1);
00568     rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1);
00569     rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1);
00570     rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, -1);
00571 
00572     DEF_OSSL_PKEY_BN(cRSA, rsa, n);
00573     DEF_OSSL_PKEY_BN(cRSA, rsa, e);
00574     DEF_OSSL_PKEY_BN(cRSA, rsa, d);
00575     DEF_OSSL_PKEY_BN(cRSA, rsa, p);
00576     DEF_OSSL_PKEY_BN(cRSA, rsa, q);
00577     DEF_OSSL_PKEY_BN(cRSA, rsa, dmp1);
00578     DEF_OSSL_PKEY_BN(cRSA, rsa, dmq1);
00579     DEF_OSSL_PKEY_BN(cRSA, rsa, iqmp);
00580 
00581     rb_define_method(cRSA, "params", ossl_rsa_get_params, 0);
00582 
00583     DefRSAConst(PKCS1_PADDING);
00584     DefRSAConst(SSLV23_PADDING);
00585     DefRSAConst(NO_PADDING);
00586     DefRSAConst(PKCS1_OAEP_PADDING);
00587 
00588 /*
00589  * TODO: Test it
00590     rb_define_method(cRSA, "blinding_on!", ossl_rsa_blinding_on, 0);
00591     rb_define_method(cRSA, "blinding_off!", ossl_rsa_blinding_off, 0);
00592  */
00593 }
00594 
00595 #else /* defined NO_RSA */
00596 void
00597 Init_ossl_rsa()
00598 {
00599 }
00600 #endif /* NO_RSA */
00601 
00602 

Generated on Sat Jul 7 2012 15:29:11 for Ruby by  doxygen 1.7.1