2 * $Id: ossl_pkey.c 12043 2007-03-12 04:12:32Z knu $
3 * 'OpenSSL for Ruby' project
4 * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
8 * This program is licenced under the same licence as Ruby.
9 * (See the file 'LICENCE'.)
22 * callback for generating keys
25 ossl_generate_cb(int p
, int n
, void *arg
)
30 rb_ary_store(ary
, 0, INT2NUM(p
));
31 rb_ary_store(ary
, 1, INT2NUM(n
));
40 ossl_pkey_new(EVP_PKEY
*pkey
)
43 ossl_raise(ePKeyError
, "Cannot make new key from NULL.");
45 switch (EVP_PKEY_type(pkey
->type
)) {
46 #if !defined(OPENSSL_NO_RSA)
48 return ossl_rsa_new(pkey
);
50 #if !defined(OPENSSL_NO_DSA)
52 return ossl_dsa_new(pkey
);
54 #if !defined(OPENSSL_NO_DH)
56 return ossl_dh_new(pkey
);
59 ossl_raise(ePKeyError
, "unsupported key type");
61 return Qnil
; /* not reached */
65 ossl_pkey_new_from_file(VALUE filename
)
70 SafeStringValue(filename
);
71 if (!(fp
= fopen(RSTRING(filename
)->ptr
, "r"))) {
72 ossl_raise(ePKeyError
, "%s", strerror(errno
));
75 pkey
= PEM_read_PrivateKey(fp
, NULL
, ossl_pem_passwd_cb
, NULL
);
78 ossl_raise(ePKeyError
, NULL
);
81 return ossl_pkey_new(pkey
);
89 SafeGetPKey(obj
, pkey
);
95 GetPrivPKeyPtr(VALUE obj
)
99 if (rb_funcall(obj
, id_private_q
, 0, NULL
) != Qtrue
) {
100 ossl_raise(rb_eArgError
, "Private key is needed.");
102 SafeGetPKey(obj
, pkey
);
108 DupPKeyPtr(VALUE obj
)
112 SafeGetPKey(obj
, pkey
);
113 CRYPTO_add(&pkey
->references
, 1, CRYPTO_LOCK_EVP_PKEY
);
119 DupPrivPKeyPtr(VALUE obj
)
123 if (rb_funcall(obj
, id_private_q
, 0, NULL
) != Qtrue
) {
124 ossl_raise(rb_eArgError
, "Private key is needed.");
126 SafeGetPKey(obj
, pkey
);
127 CRYPTO_add(&pkey
->references
, 1, CRYPTO_LOCK_EVP_PKEY
);
136 ossl_pkey_alloc(VALUE klass
)
141 if (!(pkey
= EVP_PKEY_new())) {
142 ossl_raise(ePKeyError
, NULL
);
144 WrapPKey(klass
, obj
, pkey
);
150 ossl_pkey_initialize(VALUE self
)
152 if (rb_obj_is_instance_of(self
, cPKey
)) {
153 ossl_raise(rb_eNotImpError
, "OpenSSL::PKey::PKey is an abstract class.");
159 ossl_pkey_sign(VALUE self
, VALUE digest
, VALUE data
)
166 if (rb_funcall(self
, id_private_q
, 0, NULL
) != Qtrue
) {
167 ossl_raise(rb_eArgError
, "Private key is needed.");
170 EVP_SignInit(&ctx
, GetDigestPtr(digest
));
172 EVP_SignUpdate(&ctx
, RSTRING(data
)->ptr
, RSTRING(data
)->len
);
173 str
= rb_str_new(0, EVP_PKEY_size(pkey
)+16);
174 if (!EVP_SignFinal(&ctx
, RSTRING(str
)->ptr
, &buf_len
, pkey
))
175 ossl_raise(ePKeyError
, NULL
);
176 assert(buf_len
<= RSTRING(str
)->len
);
177 RSTRING(str
)->len
= buf_len
;
178 RSTRING(str
)->ptr
[buf_len
] = 0;
184 ossl_pkey_verify(VALUE self
, VALUE digest
, VALUE sig
, VALUE data
)
190 EVP_VerifyInit(&ctx
, GetDigestPtr(digest
));
193 EVP_VerifyUpdate(&ctx
, RSTRING(data
)->ptr
, RSTRING(data
)->len
);
194 switch (EVP_VerifyFinal(&ctx
, RSTRING(sig
)->ptr
, RSTRING(sig
)->len
, pkey
)) {
200 ossl_raise(ePKeyError
, NULL
);
202 return Qnil
; /* dummy */
211 #if 0 /* let rdoc know about mOSSL */
212 mOSSL
= rb_define_module("OpenSSL");
215 mPKey
= rb_define_module_under(mOSSL
, "PKey");
217 ePKeyError
= rb_define_class_under(mPKey
, "PKeyError", eOSSLError
);
219 cPKey
= rb_define_class_under(mPKey
, "PKey", rb_cObject
);
221 rb_define_alloc_func(cPKey
, ossl_pkey_alloc
);
222 rb_define_method(cPKey
, "initialize", ossl_pkey_initialize
, 0);
224 rb_define_method(cPKey
, "sign", ossl_pkey_sign
, 2);
225 rb_define_method(cPKey
, "verify", ossl_pkey_verify
, 3);
227 id_private_q
= rb_intern("private?");