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

ext/openssl/ossl_pkey.c

Go to the documentation of this file.
00001 /*
00002  * $Id: ossl_pkey.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 #include "ossl.h"
00012 
00013 /*
00014  * Classes
00015  */
00016 VALUE mPKey;
00017 VALUE cPKey;
00018 VALUE ePKeyError;
00019 ID id_private_q;
00020 
00021 /*
00022  * callback for generating keys
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 /*
00037  * Public
00038  */
00039 VALUE
00040 ossl_pkey_new(EVP_PKEY *pkey)
00041 {
00042     if (!pkey) {
00043         ossl_raise(ePKeyError, "Cannot make new key from NULL.");
00044     }
00045     switch (EVP_PKEY_type(pkey->type)) {
00046 #if !defined(OPENSSL_NO_RSA)
00047     case EVP_PKEY_RSA:
00048         return ossl_rsa_new(pkey);
00049 #endif
00050 #if !defined(OPENSSL_NO_DSA)
00051     case EVP_PKEY_DSA:
00052         return ossl_dsa_new(pkey);
00053 #endif
00054 #if !defined(OPENSSL_NO_DH)
00055     case EVP_PKEY_DH:
00056         return ossl_dh_new(pkey);
00057 #endif
00058 #if !defined(OPENSSL_NO_EC) && (OPENSSL_VERSION_NUMBER >= 0x0090802fL)
00059     case EVP_PKEY_EC:
00060         return ossl_ec_new(pkey);
00061 #endif
00062     default:
00063         ossl_raise(ePKeyError, "unsupported key type");
00064     }
00065     return Qnil; /* not reached */
00066 }
00067 
00068 VALUE
00069 ossl_pkey_new_from_file(VALUE filename)
00070 {
00071     FILE *fp;
00072     EVP_PKEY *pkey;
00073 
00074     SafeStringValue(filename);
00075     if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
00076         ossl_raise(ePKeyError, "%s", strerror(errno));
00077     }
00078 
00079     pkey = PEM_read_PrivateKey(fp, NULL, ossl_pem_passwd_cb, NULL);
00080     fclose(fp);
00081     if (!pkey) {
00082         ossl_raise(ePKeyError, NULL);
00083     }
00084 
00085     return ossl_pkey_new(pkey);
00086 }
00087 
00088 EVP_PKEY *
00089 GetPKeyPtr(VALUE obj)
00090 {
00091     EVP_PKEY *pkey;
00092 
00093     SafeGetPKey(obj, pkey);
00094 
00095     return pkey;
00096 }
00097 
00098 EVP_PKEY *
00099 GetPrivPKeyPtr(VALUE obj)
00100 {
00101     EVP_PKEY *pkey;
00102 
00103     if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) {
00104         ossl_raise(rb_eArgError, "Private key is needed.");
00105     }
00106     SafeGetPKey(obj, pkey);
00107 
00108     return pkey;
00109 }
00110 
00111 EVP_PKEY *
00112 DupPKeyPtr(VALUE obj)
00113 {
00114     EVP_PKEY *pkey;
00115 
00116     SafeGetPKey(obj, pkey);
00117     CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
00118 
00119     return pkey;
00120 }
00121 
00122 EVP_PKEY *
00123 DupPrivPKeyPtr(VALUE obj)
00124 {
00125     EVP_PKEY *pkey;
00126 
00127     if (rb_funcall(obj, id_private_q, 0, NULL) != Qtrue) {
00128         ossl_raise(rb_eArgError, "Private key is needed.");
00129     }
00130     SafeGetPKey(obj, pkey);
00131     CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
00132 
00133     return pkey;
00134 }
00135 
00136 /*
00137  * Private
00138  */
00139 static VALUE
00140 ossl_pkey_alloc(VALUE klass)
00141 {
00142     EVP_PKEY *pkey;
00143     VALUE obj;
00144 
00145     if (!(pkey = EVP_PKEY_new())) {
00146         ossl_raise(ePKeyError, NULL);
00147     }
00148     WrapPKey(klass, obj, pkey);
00149 
00150     return obj;
00151 }
00152 
00153 static VALUE
00154 ossl_pkey_initialize(VALUE self)
00155 {
00156     if (rb_obj_is_instance_of(self, cPKey)) {
00157         ossl_raise(rb_eNotImpError, "OpenSSL::PKey::PKey is an abstract class.");
00158     }
00159     return self;
00160 }
00161 
00162 static VALUE
00163 ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
00164 {
00165     EVP_PKEY *pkey;
00166     EVP_MD_CTX ctx;
00167     unsigned int buf_len;
00168     VALUE str;
00169 
00170     if (rb_funcall(self, id_private_q, 0, NULL) != Qtrue) {
00171         ossl_raise(rb_eArgError, "Private key is needed.");
00172     }
00173     GetPKey(self, pkey);
00174     EVP_SignInit(&ctx, GetDigestPtr(digest));
00175     StringValue(data);
00176     EVP_SignUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
00177     str = rb_str_new(0, EVP_PKEY_size(pkey)+16);
00178     if (!EVP_SignFinal(&ctx, (unsigned char *)RSTRING_PTR(str), &buf_len, pkey))
00179         ossl_raise(ePKeyError, NULL);
00180     assert((long)buf_len <= RSTRING_LEN(str));
00181     rb_str_set_len(str, buf_len);
00182 
00183     return str;
00184 }
00185 
00186 static VALUE
00187 ossl_pkey_verify(VALUE self, VALUE digest, VALUE sig, VALUE data)
00188 {
00189     EVP_PKEY *pkey;
00190     EVP_MD_CTX ctx;
00191 
00192     GetPKey(self, pkey);
00193     EVP_VerifyInit(&ctx, GetDigestPtr(digest));
00194     StringValue(sig);
00195     StringValue(data);
00196     EVP_VerifyUpdate(&ctx, RSTRING_PTR(data), RSTRING_LEN(data));
00197     switch (EVP_VerifyFinal(&ctx, (unsigned char *)RSTRING_PTR(sig), RSTRING_LEN(sig), pkey)) {
00198     case 0:
00199         return Qfalse;
00200     case 1:
00201         return Qtrue;
00202     default:
00203         ossl_raise(ePKeyError, NULL);
00204     }
00205     return Qnil; /* dummy */
00206 }
00207 
00208 /*
00209  * INIT
00210  */
00211 void
00212 Init_ossl_pkey()
00213 {
00214 #if 0 /* let rdoc know about mOSSL */
00215     mOSSL = rb_define_module("OpenSSL");
00216 #endif
00217 
00218     mPKey = rb_define_module_under(mOSSL, "PKey");
00219 
00220     ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
00221 
00222     cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
00223 
00224     rb_define_alloc_func(cPKey, ossl_pkey_alloc);
00225     rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
00226 
00227     rb_define_method(cPKey, "sign", ossl_pkey_sign, 2);
00228     rb_define_method(cPKey, "verify", ossl_pkey_verify, 3);
00229 
00230     id_private_q = rb_intern("private?");
00231 
00232     /*
00233      * INIT rsa, dsa, dh, ec
00234      */
00235     Init_ossl_rsa();
00236     Init_ossl_dsa();
00237     Init_ossl_dh();
00238     Init_ossl_ec();
00239 }
00240 
00241 

Generated on Thu Sep 8 2011 03:50:35 for Ruby by  doxygen 1.7.1