|
Ruby 1.9.2p290(2011-07-09revision32553)
|
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
1.7.3