• 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 27440 2010-04-22 08:21:01Z nobu $
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             rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL);
00156         }
00157         if (!rsa) {
00158             (void)BIO_reset(in);
00159             rsa = PEM_read_bio_RSA_PUBKEY(in, NULL, NULL, NULL);
00160         }
00161         if (!rsa) {
00162             (void)BIO_reset(in);
00163             rsa = d2i_RSAPrivateKey_bio(in, NULL);
00164         }
00165         if (!rsa) {
00166             (void)BIO_reset(in);
00167             rsa = d2i_RSAPublicKey_bio(in, NULL);
00168         }
00169         if (!rsa) {
00170             (void)BIO_reset(in);
00171             rsa = d2i_RSA_PUBKEY_bio(in, NULL);
00172         }
00173         BIO_free(in);
00174         if (!rsa) ossl_raise(eRSAError, "Neither PUB key nor PRIV key:");
00175     }
00176     if (!EVP_PKEY_assign_RSA(pkey, rsa)) {
00177         RSA_free(rsa);
00178         ossl_raise(eRSAError, NULL);
00179     }
00180 
00181     return self;
00182 }
00183 
00184 /*
00185  *  call-seq:
00186  *     rsa.public? -> true
00187  *
00188  *  The return value is always true since every private key is also a public key.
00189  *
00190  */
00191 static VALUE
00192 ossl_rsa_is_public(VALUE self)
00193 {
00194     EVP_PKEY *pkey;
00195 
00196     GetPKeyRSA(self, pkey);
00197     /*
00198      * This method should check for n and e.  BUG.
00199      */
00200     return Qtrue;
00201 }
00202 
00203 /*
00204  *  call-seq:
00205  *     rsa.private? -> true | false
00206  *
00207  */
00208 static VALUE
00209 ossl_rsa_is_private(VALUE self)
00210 {
00211     EVP_PKEY *pkey;
00212 
00213     GetPKeyRSA(self, pkey);
00214 
00215     return (RSA_PRIVATE(self, pkey->pkey.rsa)) ? Qtrue : Qfalse;
00216 }
00217 
00218 /*
00219  *  call-seq:
00220  *     rsa.to_pem([cipher, pass]) -> aString
00221  *
00222  *  === Parameters
00223  *  * +cipher+ is a Cipher object.
00224  *  * +pass+ is a string.
00225  *
00226  *  === Examples
00227  *  * rsa.to_pem -> aString
00228  *  * rsa.to_pem(cipher, pass) -> aString
00229  */
00230 static VALUE
00231 ossl_rsa_export(int argc, VALUE *argv, VALUE self)
00232 {
00233     EVP_PKEY *pkey;
00234     BIO *out;
00235     const EVP_CIPHER *ciph = NULL;
00236     char *passwd = NULL;
00237     VALUE cipher, pass, str;
00238 
00239     GetPKeyRSA(self, pkey);
00240 
00241     rb_scan_args(argc, argv, "02", &cipher, &pass);
00242 
00243     if (!NIL_P(cipher)) {
00244         ciph = GetCipherPtr(cipher);
00245         if (!NIL_P(pass)) {
00246             passwd = StringValuePtr(pass);
00247         }
00248     }
00249     if (!(out = BIO_new(BIO_s_mem()))) {
00250         ossl_raise(eRSAError, NULL);
00251     }
00252     if (RSA_HAS_PRIVATE(pkey->pkey.rsa)) {
00253         if (!PEM_write_bio_RSAPrivateKey(out, pkey->pkey.rsa, ciph,
00254                                          NULL, 0, ossl_pem_passwd_cb, passwd)) {
00255             BIO_free(out);
00256             ossl_raise(eRSAError, NULL);
00257         }
00258     } else {
00259         if (!PEM_write_bio_RSAPublicKey(out, pkey->pkey.rsa)) {
00260             BIO_free(out);
00261             ossl_raise(eRSAError, NULL);
00262         }
00263     }
00264     str = ossl_membio2str(out);
00265 
00266     return str;
00267 }
00268 
00269 /*
00270  *  call-seq:
00271  *     rsa.to_der -> aString
00272  *
00273  */
00274 static VALUE
00275 ossl_rsa_to_der(VALUE self)
00276 {
00277     EVP_PKEY *pkey;
00278     int (*i2d_func)_((const RSA*, unsigned char**));
00279     unsigned char *p;
00280     long len;
00281     VALUE str;
00282 
00283     GetPKeyRSA(self, pkey);
00284     if(RSA_HAS_PRIVATE(pkey->pkey.rsa))
00285         i2d_func = i2d_RSAPrivateKey;
00286     else
00287         i2d_func = i2d_RSAPublicKey;
00288     if((len = i2d_func(pkey->pkey.rsa, NULL)) <= 0)
00289         ossl_raise(eRSAError, NULL);
00290     str = rb_str_new(0, len);
00291     p = (unsigned char *)RSTRING_PTR(str);
00292     if(i2d_func(pkey->pkey.rsa, &p) < 0)
00293         ossl_raise(eRSAError, NULL);
00294     ossl_str_adjust(str, p);
00295 
00296     return str;
00297 }
00298 
00299 #define ossl_rsa_buf_size(pkey) (RSA_size((pkey)->pkey.rsa)+16)
00300 
00301 /*
00302  *  call-seq:
00303  *     rsa.public_encrypt(string [, padding]) -> aString
00304  *
00305  */
00306 static VALUE
00307 ossl_rsa_public_encrypt(int argc, VALUE *argv, VALUE self)
00308 {
00309     EVP_PKEY *pkey;
00310     int buf_len, pad;
00311     VALUE str, buffer, padding;
00312 
00313     GetPKeyRSA(self, pkey);
00314     rb_scan_args(argc, argv, "11", &buffer, &padding);
00315     pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
00316     StringValue(buffer);
00317     str = rb_str_new(0, ossl_rsa_buf_size(pkey));
00318     buf_len = RSA_public_encrypt(RSTRING_LEN(buffer), (unsigned char *)RSTRING_PTR(buffer),
00319                                  (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa,
00320                                  pad);
00321     if (buf_len < 0) ossl_raise(eRSAError, NULL);
00322     rb_str_set_len(str, buf_len);
00323 
00324     return str;
00325 }
00326 
00327 /*
00328  *  call-seq:
00329  *     rsa.public_decrypt(string [, padding]) -> aString
00330  *
00331  */
00332 static VALUE
00333 ossl_rsa_public_decrypt(int argc, VALUE *argv, VALUE self)
00334 {
00335     EVP_PKEY *pkey;
00336     int buf_len, pad;
00337     VALUE str, buffer, padding;
00338 
00339     GetPKeyRSA(self, pkey);
00340     rb_scan_args(argc, argv, "11", &buffer, &padding);
00341     pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
00342     StringValue(buffer);
00343     str = rb_str_new(0, ossl_rsa_buf_size(pkey));
00344     buf_len = RSA_public_decrypt(RSTRING_LEN(buffer), (unsigned char *)RSTRING_PTR(buffer),
00345                                  (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa,
00346                                  pad);
00347     if (buf_len < 0) ossl_raise(eRSAError, NULL);
00348     rb_str_set_len(str, buf_len);
00349 
00350     return str;
00351 }
00352 
00353 /*
00354  *  call-seq:
00355  *     rsa.private_encrypt(string [, padding]) -> aString
00356  *
00357  */
00358 static VALUE
00359 ossl_rsa_private_encrypt(int argc, VALUE *argv, VALUE self)
00360 {
00361     EVP_PKEY *pkey;
00362     int buf_len, pad;
00363     VALUE str, buffer, padding;
00364 
00365     GetPKeyRSA(self, pkey);
00366     if (!RSA_PRIVATE(self, pkey->pkey.rsa)) {
00367         ossl_raise(eRSAError, "private key needed.");
00368     }
00369     rb_scan_args(argc, argv, "11", &buffer, &padding);
00370     pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
00371     StringValue(buffer);
00372     str = rb_str_new(0, ossl_rsa_buf_size(pkey));
00373     buf_len = RSA_private_encrypt(RSTRING_LEN(buffer), (unsigned char *)RSTRING_PTR(buffer),
00374                                   (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa,
00375                                   pad);
00376     if (buf_len < 0) ossl_raise(eRSAError, NULL);
00377     rb_str_set_len(str, buf_len);
00378 
00379     return str;
00380 }
00381 
00382 
00383 /*
00384  *  call-seq:
00385  *     rsa.private_decrypt(string [, padding]) -> aString
00386  *
00387  */
00388 static VALUE
00389 ossl_rsa_private_decrypt(int argc, VALUE *argv, VALUE self)
00390 {
00391     EVP_PKEY *pkey;
00392     int buf_len, pad;
00393     VALUE str, buffer, padding;
00394 
00395     GetPKeyRSA(self, pkey);
00396     if (!RSA_PRIVATE(self, pkey->pkey.rsa)) {
00397         ossl_raise(eRSAError, "private key needed.");
00398     }
00399     rb_scan_args(argc, argv, "11", &buffer, &padding);
00400     pad = (argc == 1) ? RSA_PKCS1_PADDING : NUM2INT(padding);
00401     StringValue(buffer);
00402     str = rb_str_new(0, ossl_rsa_buf_size(pkey));
00403     buf_len = RSA_private_decrypt(RSTRING_LEN(buffer), (unsigned char *)RSTRING_PTR(buffer),
00404                                   (unsigned char *)RSTRING_PTR(str), pkey->pkey.rsa,
00405                                   pad);
00406     if (buf_len < 0) ossl_raise(eRSAError, NULL);
00407     rb_str_set_len(str, buf_len);
00408 
00409     return str;
00410 }
00411 
00412 /*
00413  *  call-seq:
00414  *     rsa.params -> hash
00415  *
00416  * Stores all parameters of key to the hash
00417  * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
00418  * Don't use :-)) (I's up to you)
00419  */
00420 static VALUE
00421 ossl_rsa_get_params(VALUE self)
00422 {
00423     EVP_PKEY *pkey;
00424     VALUE hash;
00425 
00426     GetPKeyRSA(self, pkey);
00427 
00428     hash = rb_hash_new();
00429 
00430     rb_hash_aset(hash, rb_str_new2("n"), ossl_bn_new(pkey->pkey.rsa->n));
00431     rb_hash_aset(hash, rb_str_new2("e"), ossl_bn_new(pkey->pkey.rsa->e));
00432     rb_hash_aset(hash, rb_str_new2("d"), ossl_bn_new(pkey->pkey.rsa->d));
00433     rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(pkey->pkey.rsa->p));
00434     rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(pkey->pkey.rsa->q));
00435     rb_hash_aset(hash, rb_str_new2("dmp1"), ossl_bn_new(pkey->pkey.rsa->dmp1));
00436     rb_hash_aset(hash, rb_str_new2("dmq1"), ossl_bn_new(pkey->pkey.rsa->dmq1));
00437     rb_hash_aset(hash, rb_str_new2("iqmp"), ossl_bn_new(pkey->pkey.rsa->iqmp));
00438 
00439     return hash;
00440 }
00441 
00442 /*
00443  *  call-seq:
00444  *     rsa.to_text -> aString
00445  *
00446  * Prints all parameters of key to buffer
00447  * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
00448  * Don't use :-)) (It's up to you)
00449  */
00450 static VALUE
00451 ossl_rsa_to_text(VALUE self)
00452 {
00453     EVP_PKEY *pkey;
00454     BIO *out;
00455     VALUE str;
00456 
00457     GetPKeyRSA(self, pkey);
00458     if (!(out = BIO_new(BIO_s_mem()))) {
00459         ossl_raise(eRSAError, NULL);
00460     }
00461     if (!RSA_print(out, pkey->pkey.rsa, 0)) { /* offset = 0 */
00462         BIO_free(out);
00463         ossl_raise(eRSAError, NULL);
00464     }
00465     str = ossl_membio2str(out);
00466 
00467     return str;
00468 }
00469 
00470 /*
00471  *  call-seq:
00472  *     rsa.public_key -> aRSA
00473  *
00474  * Makes new instance RSA PUBLIC_KEY from PRIVATE_KEY
00475  */
00476 static VALUE
00477 ossl_rsa_to_public_key(VALUE self)
00478 {
00479     EVP_PKEY *pkey;
00480     RSA *rsa;
00481     VALUE obj;
00482 
00483     GetPKeyRSA(self, pkey);
00484     /* err check performed by rsa_instance */
00485     rsa = RSAPublicKey_dup(pkey->pkey.rsa);
00486     obj = rsa_instance(CLASS_OF(self), rsa);
00487     if (obj == Qfalse) {
00488         RSA_free(rsa);
00489         ossl_raise(eRSAError, NULL);
00490     }
00491     return obj;
00492 }
00493 
00494 /*
00495  * TODO: Test me
00496 
00497 static VALUE
00498 ossl_rsa_blinding_on(VALUE self)
00499 {
00500     EVP_PKEY *pkey;
00501 
00502     GetPKeyRSA(self, pkey);
00503 
00504     if (RSA_blinding_on(pkey->pkey.rsa, ossl_bn_ctx) != 1) {
00505         ossl_raise(eRSAError, NULL);
00506     }
00507     return self;
00508 }
00509 
00510 static VALUE
00511 ossl_rsa_blinding_off(VALUE self)
00512 {
00513     EVP_PKEY *pkey;
00514 
00515     GetPKeyRSA(self, pkey);
00516     RSA_blinding_off(pkey->pkey.rsa);
00517 
00518     return self;
00519 }
00520  */
00521 
00522 OSSL_PKEY_BN(rsa, n)
00523 OSSL_PKEY_BN(rsa, e)
00524 OSSL_PKEY_BN(rsa, d)
00525 OSSL_PKEY_BN(rsa, p)
00526 OSSL_PKEY_BN(rsa, q)
00527 OSSL_PKEY_BN(rsa, dmp1)
00528 OSSL_PKEY_BN(rsa, dmq1)
00529 OSSL_PKEY_BN(rsa, iqmp)
00530 
00531 /*
00532  * INIT
00533  */
00534 #define DefRSAConst(x) rb_define_const(cRSA, #x,INT2FIX(RSA_##x))
00535 
00536 void
00537 Init_ossl_rsa()
00538 {
00539 #if 0 /* let rdoc know about mOSSL and mPKey */
00540     mOSSL = rb_define_module("OpenSSL");
00541     mPKey = rb_define_module_under(mOSSL, "PKey");
00542 #endif
00543 
00544     eRSAError = rb_define_class_under(mPKey, "RSAError", ePKeyError);
00545 
00546     cRSA = rb_define_class_under(mPKey, "RSA", cPKey);
00547 
00548     rb_define_singleton_method(cRSA, "generate", ossl_rsa_s_generate, -1);
00549     rb_define_method(cRSA, "initialize", ossl_rsa_initialize, -1);
00550 
00551     rb_define_method(cRSA, "public?", ossl_rsa_is_public, 0);
00552     rb_define_method(cRSA, "private?", ossl_rsa_is_private, 0);
00553     rb_define_method(cRSA, "to_text", ossl_rsa_to_text, 0);
00554     rb_define_method(cRSA, "export", ossl_rsa_export, -1);
00555     rb_define_alias(cRSA, "to_pem", "export");
00556     rb_define_alias(cRSA, "to_s", "export");
00557     rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0);
00558     rb_define_method(cRSA, "public_key", ossl_rsa_to_public_key, 0);
00559     rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, -1);
00560     rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1);
00561     rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1);
00562     rb_define_method(cRSA, "private_decrypt", ossl_rsa_private_decrypt, -1);
00563 
00564     DEF_OSSL_PKEY_BN(cRSA, rsa, n);
00565     DEF_OSSL_PKEY_BN(cRSA, rsa, e);
00566     DEF_OSSL_PKEY_BN(cRSA, rsa, d);
00567     DEF_OSSL_PKEY_BN(cRSA, rsa, p);
00568     DEF_OSSL_PKEY_BN(cRSA, rsa, q);
00569     DEF_OSSL_PKEY_BN(cRSA, rsa, dmp1);
00570     DEF_OSSL_PKEY_BN(cRSA, rsa, dmq1);
00571     DEF_OSSL_PKEY_BN(cRSA, rsa, iqmp);
00572 
00573     rb_define_method(cRSA, "params", ossl_rsa_get_params, 0);
00574 
00575     DefRSAConst(PKCS1_PADDING);
00576     DefRSAConst(SSLV23_PADDING);
00577     DefRSAConst(NO_PADDING);
00578     DefRSAConst(PKCS1_OAEP_PADDING);
00579 
00580 /*
00581  * TODO: Test it
00582     rb_define_method(cRSA, "blinding_on!", ossl_rsa_blinding_on, 0);
00583     rb_define_method(cRSA, "blinding_off!", ossl_rsa_blinding_off, 0);
00584  */
00585 }
00586 
00587 #else /* defined NO_RSA */
00588 void
00589 Init_ossl_rsa()
00590 {
00591 }
00592 #endif /* NO_RSA */
00593 
00594 

Generated on Wed Sep 8 2010 09:55:20 for Ruby by  doxygen 1.7.1