Ruby 1.9.2p136(2010-12-25revision30365)

- 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