00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "ossl.h"
00012
00013
00014
00015
00016 VALUE mPKey;
00017 VALUE cPKey;
00018 VALUE ePKeyError;
00019 ID id_private_q;
00020
00021
00022
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
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;
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
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;
00206 }
00207
00208
00209
00210
00211 void
00212 Init_ossl_pkey()
00213 {
00214 #if 0
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
00234
00235 Init_ossl_rsa();
00236 Init_ossl_dsa();
00237 Init_ossl_dh();
00238 Init_ossl_ec();
00239 }
00240
00241