2 * $Id: ossl_pkey_rsa.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'.)
11 #if !defined(OPENSSL_NO_RSA)
15 #define GetPKeyRSA(obj, pkey) do { \
17 if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) { /* PARANOIA? */ \
18 ossl_raise(rb_eRuntimeError, "THIS IS NOT A RSA!") ; \
22 #define RSA_HAS_PRIVATE(rsa) ((rsa)->p && (rsa)->q)
23 #define RSA_PRIVATE(obj,rsa) (RSA_HAS_PRIVATE(rsa)||OSSL_PKEY_IS_PRIVATE(obj))
35 rsa_instance(VALUE klass
, RSA
*rsa
)
43 if (!(pkey
= EVP_PKEY_new())) {
46 if (!EVP_PKEY_assign_RSA(pkey
, rsa
)) {
50 WrapPKey(klass
, obj
, pkey
);
56 ossl_rsa_new(EVP_PKEY
*pkey
)
61 obj
= rsa_instance(cRSA
, RSA_new());
64 if (EVP_PKEY_type(pkey
->type
) != EVP_PKEY_RSA
) {
65 ossl_raise(rb_eTypeError
, "Not a RSA key!");
67 WrapPKey(cRSA
, obj
, pkey
);
70 ossl_raise(eRSAError
, NULL
);
80 rsa_generate(int size
, int exp
)
82 return RSA_generate_key(size
, exp
,
83 rb_block_given_p() ? ossl_generate_cb
: NULL
,
88 ossl_rsa_s_generate(int argc
, VALUE
*argv
, VALUE klass
)
94 rb_scan_args(argc
, argv
, "11", &size
, &exp
);
96 rsa
= rsa_generate(NUM2INT(size
), NIL_P(exp
) ? RSA_F4
: NUM2INT(exp
)); /* err handled by rsa_instance */
97 obj
= rsa_instance(klass
, rsa
);
101 ossl_raise(eRSAError
, NULL
);
108 ossl_rsa_initialize(int argc
, VALUE
*argv
, VALUE self
)
117 if(rb_scan_args(argc
, argv
, "02", &arg
, &pass
) == 0) {
120 else if (FIXNUM_P(arg
)) {
121 rsa
= rsa_generate(FIX2INT(arg
), NIL_P(pass
) ? RSA_F4
: NUM2INT(pass
));
122 if (!rsa
) ossl_raise(eRSAError
, NULL
);
125 if (!NIL_P(pass
)) passwd
= StringValuePtr(pass
);
126 arg
= ossl_to_der_if_possible(arg
);
127 in
= ossl_obj2bio(arg
);
128 rsa
= PEM_read_bio_RSAPrivateKey(in
, NULL
, ossl_pem_passwd_cb
, passwd
);
131 rsa
= PEM_read_bio_RSAPublicKey(in
, NULL
, NULL
, NULL
);
135 rsa
= PEM_read_bio_RSA_PUBKEY(in
, NULL
, NULL
, NULL
);
139 rsa
= d2i_RSAPrivateKey_bio(in
, NULL
);
143 rsa
= d2i_RSAPublicKey_bio(in
, NULL
);
147 rsa
= d2i_RSA_PUBKEY_bio(in
, NULL
);
150 if (!rsa
) ossl_raise(eRSAError
, "Neither PUB key nor PRIV key:");
152 if (!EVP_PKEY_assign_RSA(pkey
, rsa
)) {
154 ossl_raise(eRSAError
, NULL
);
161 ossl_rsa_is_public(VALUE self
)
165 GetPKeyRSA(self
, pkey
);
168 * Every key is public at the same time!
174 ossl_rsa_is_private(VALUE self
)
178 GetPKeyRSA(self
, pkey
);
180 return (RSA_PRIVATE(self
, pkey
->pkey
.rsa
)) ? Qtrue
: Qfalse
;
184 ossl_rsa_export(int argc
, VALUE
*argv
, VALUE self
)
188 const EVP_CIPHER
*ciph
= NULL
;
190 VALUE cipher
, pass
, str
;
192 GetPKeyRSA(self
, pkey
);
194 rb_scan_args(argc
, argv
, "02", &cipher
, &pass
);
196 if (!NIL_P(cipher
)) {
197 ciph
= GetCipherPtr(cipher
);
199 passwd
= StringValuePtr(pass
);
202 if (!(out
= BIO_new(BIO_s_mem()))) {
203 ossl_raise(eRSAError
, NULL
);
205 if (RSA_HAS_PRIVATE(pkey
->pkey
.rsa
)) {
206 if (!PEM_write_bio_RSAPrivateKey(out
, pkey
->pkey
.rsa
, ciph
,
207 NULL
, 0, ossl_pem_passwd_cb
, passwd
)) {
209 ossl_raise(eRSAError
, NULL
);
212 if (!PEM_write_bio_RSAPublicKey(out
, pkey
->pkey
.rsa
)) {
214 ossl_raise(eRSAError
, NULL
);
217 str
= ossl_membio2str(out
);
223 ossl_rsa_to_der(VALUE self
)
226 int (*i2d_func
)_((const RSA
*, unsigned char**));
231 GetPKeyRSA(self
, pkey
);
232 if(RSA_HAS_PRIVATE(pkey
->pkey
.rsa
))
233 i2d_func
= i2d_RSAPrivateKey
;
235 i2d_func
= i2d_RSAPublicKey
;
236 if((len
= i2d_func(pkey
->pkey
.rsa
, NULL
)) <= 0)
237 ossl_raise(eRSAError
, NULL
);
238 str
= rb_str_new(0, len
);
239 p
= RSTRING(str
)->ptr
;
240 if(i2d_func(pkey
->pkey
.rsa
, &p
) < 0)
241 ossl_raise(eRSAError
, NULL
);
242 ossl_str_adjust(str
, p
);
247 #define ossl_rsa_buf_size(pkey) (RSA_size((pkey)->pkey.rsa)+16)
250 ossl_rsa_public_encrypt(int argc
, VALUE
*argv
, VALUE self
)
254 VALUE str
, buffer
, padding
;
256 GetPKeyRSA(self
, pkey
);
257 rb_scan_args(argc
, argv
, "11", &buffer
, &padding
);
258 pad
= (argc
== 1) ? RSA_PKCS1_PADDING
: NUM2INT(padding
);
260 str
= rb_str_new(0, ossl_rsa_buf_size(pkey
));
261 buf_len
= RSA_public_encrypt(RSTRING(buffer
)->len
, RSTRING(buffer
)->ptr
,
262 RSTRING(str
)->ptr
, pkey
->pkey
.rsa
,
264 if (buf_len
< 0) ossl_raise(eRSAError
, NULL
);
265 RSTRING(str
)->len
= buf_len
;
266 RSTRING(str
)->ptr
[buf_len
] = 0;
272 ossl_rsa_public_decrypt(int argc
, VALUE
*argv
, VALUE self
)
276 VALUE str
, buffer
, padding
;
278 GetPKeyRSA(self
, pkey
);
279 rb_scan_args(argc
, argv
, "11", &buffer
, &padding
);
280 pad
= (argc
== 1) ? RSA_PKCS1_PADDING
: NUM2INT(padding
);
282 str
= rb_str_new(0, ossl_rsa_buf_size(pkey
));
283 buf_len
= RSA_public_decrypt(RSTRING(buffer
)->len
, RSTRING(buffer
)->ptr
,
284 RSTRING(str
)->ptr
, pkey
->pkey
.rsa
,
286 if (buf_len
< 0) ossl_raise(eRSAError
, NULL
);
287 RSTRING(str
)->len
= buf_len
;
288 RSTRING(str
)->ptr
[buf_len
] = 0;
294 ossl_rsa_private_encrypt(int argc
, VALUE
*argv
, VALUE self
)
298 VALUE str
, buffer
, padding
;
300 GetPKeyRSA(self
, pkey
);
301 if (!RSA_PRIVATE(self
, pkey
->pkey
.rsa
)) {
302 ossl_raise(eRSAError
, "private key needed.");
304 rb_scan_args(argc
, argv
, "11", &buffer
, &padding
);
305 pad
= (argc
== 1) ? RSA_PKCS1_PADDING
: NUM2INT(padding
);
307 str
= rb_str_new(0, ossl_rsa_buf_size(pkey
));
308 buf_len
= RSA_private_encrypt(RSTRING(buffer
)->len
, RSTRING(buffer
)->ptr
,
309 RSTRING(str
)->ptr
, pkey
->pkey
.rsa
,
311 if (buf_len
< 0) ossl_raise(eRSAError
, NULL
);
312 RSTRING(str
)->len
= buf_len
;
313 RSTRING(str
)->ptr
[buf_len
] = 0;
319 ossl_rsa_private_decrypt(int argc
, VALUE
*argv
, VALUE self
)
323 VALUE str
, buffer
, padding
;
325 GetPKeyRSA(self
, pkey
);
326 if (!RSA_PRIVATE(self
, pkey
->pkey
.rsa
)) {
327 ossl_raise(eRSAError
, "private key needed.");
329 rb_scan_args(argc
, argv
, "11", &buffer
, &padding
);
330 pad
= (argc
== 1) ? RSA_PKCS1_PADDING
: NUM2INT(padding
);
332 str
= rb_str_new(0, ossl_rsa_buf_size(pkey
));
333 buf_len
= RSA_private_decrypt(RSTRING(buffer
)->len
, RSTRING(buffer
)->ptr
,
334 RSTRING(str
)->ptr
, pkey
->pkey
.rsa
,
336 if (buf_len
< 0) ossl_raise(eRSAError
, NULL
);
337 RSTRING(str
)->len
= buf_len
;
338 RSTRING(str
)->ptr
[buf_len
] = 0;
344 * Stores all parameters of key to the hash
345 * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
346 * Don't use :-)) (I's up to you)
349 ossl_rsa_get_params(VALUE self
)
354 GetPKeyRSA(self
, pkey
);
356 hash
= rb_hash_new();
358 rb_hash_aset(hash
, rb_str_new2("n"), ossl_bn_new(pkey
->pkey
.rsa
->n
));
359 rb_hash_aset(hash
, rb_str_new2("e"), ossl_bn_new(pkey
->pkey
.rsa
->e
));
360 rb_hash_aset(hash
, rb_str_new2("d"), ossl_bn_new(pkey
->pkey
.rsa
->d
));
361 rb_hash_aset(hash
, rb_str_new2("p"), ossl_bn_new(pkey
->pkey
.rsa
->p
));
362 rb_hash_aset(hash
, rb_str_new2("q"), ossl_bn_new(pkey
->pkey
.rsa
->q
));
363 rb_hash_aset(hash
, rb_str_new2("dmp1"), ossl_bn_new(pkey
->pkey
.rsa
->dmp1
));
364 rb_hash_aset(hash
, rb_str_new2("dmq1"), ossl_bn_new(pkey
->pkey
.rsa
->dmq1
));
365 rb_hash_aset(hash
, rb_str_new2("iqmp"), ossl_bn_new(pkey
->pkey
.rsa
->iqmp
));
371 * Prints all parameters of key to buffer
372 * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
373 * Don't use :-)) (It's up to you)
376 ossl_rsa_to_text(VALUE self
)
382 GetPKeyRSA(self
, pkey
);
383 if (!(out
= BIO_new(BIO_s_mem()))) {
384 ossl_raise(eRSAError
, NULL
);
386 if (!RSA_print(out
, pkey
->pkey
.rsa
, 0)) { /* offset = 0 */
388 ossl_raise(eRSAError
, NULL
);
390 str
= ossl_membio2str(out
);
396 * Makes new instance RSA PUBLIC_KEY from PRIVATE_KEY
399 ossl_rsa_to_public_key(VALUE self
)
405 GetPKeyRSA(self
, pkey
);
406 /* err check performed by rsa_instance */
407 rsa
= RSAPublicKey_dup(pkey
->pkey
.rsa
);
408 obj
= rsa_instance(CLASS_OF(self
), rsa
);
411 ossl_raise(eRSAError
, NULL
);
418 extern BN_CTX *ossl_bn_ctx;
421 ossl_rsa_blinding_on(VALUE self)
425 GetPKeyRSA(self, pkey);
427 if (RSA_blinding_on(pkey->pkey.rsa, ossl_bn_ctx) != 1) {
428 ossl_raise(eRSAError, NULL);
434 ossl_rsa_blinding_off(VALUE self)
438 GetPKeyRSA(self, pkey);
439 RSA_blinding_off(pkey->pkey.rsa);
445 OSSL_PKEY_BN(rsa
, n
);
446 OSSL_PKEY_BN(rsa
, e
);
447 OSSL_PKEY_BN(rsa
, d
);
448 OSSL_PKEY_BN(rsa
, p
);
449 OSSL_PKEY_BN(rsa
, q
);
450 OSSL_PKEY_BN(rsa
, dmp1
);
451 OSSL_PKEY_BN(rsa
, dmq1
);
452 OSSL_PKEY_BN(rsa
, iqmp
);
457 #define DefRSAConst(x) rb_define_const(cRSA, #x,INT2FIX(RSA_##x))
462 #if 0 /* let rdoc know about mOSSL and mPKey */
463 mOSSL
= rb_define_module("OpenSSL");
464 mPKey
= rb_define_module_under(mOSSL
, "PKey");
467 eRSAError
= rb_define_class_under(mPKey
, "RSAError", ePKeyError
);
469 cRSA
= rb_define_class_under(mPKey
, "RSA", cPKey
);
471 rb_define_singleton_method(cRSA
, "generate", ossl_rsa_s_generate
, -1);
472 rb_define_method(cRSA
, "initialize", ossl_rsa_initialize
, -1);
474 rb_define_method(cRSA
, "public?", ossl_rsa_is_public
, 0);
475 rb_define_method(cRSA
, "private?", ossl_rsa_is_private
, 0);
476 rb_define_method(cRSA
, "to_text", ossl_rsa_to_text
, 0);
477 rb_define_method(cRSA
, "export", ossl_rsa_export
, -1);
478 rb_define_alias(cRSA
, "to_pem", "export");
479 rb_define_alias(cRSA
, "to_s", "export");
480 rb_define_method(cRSA
, "to_der", ossl_rsa_to_der
, 0);
481 rb_define_method(cRSA
, "public_key", ossl_rsa_to_public_key
, 0);
482 rb_define_method(cRSA
, "public_encrypt", ossl_rsa_public_encrypt
, -1);
483 rb_define_method(cRSA
, "public_decrypt", ossl_rsa_public_decrypt
, -1);
484 rb_define_method(cRSA
, "private_encrypt", ossl_rsa_private_encrypt
, -1);
485 rb_define_method(cRSA
, "private_decrypt", ossl_rsa_private_decrypt
, -1);
487 DEF_OSSL_PKEY_BN(cRSA
, rsa
, n
);
488 DEF_OSSL_PKEY_BN(cRSA
, rsa
, e
);
489 DEF_OSSL_PKEY_BN(cRSA
, rsa
, d
);
490 DEF_OSSL_PKEY_BN(cRSA
, rsa
, p
);
491 DEF_OSSL_PKEY_BN(cRSA
, rsa
, q
);
492 DEF_OSSL_PKEY_BN(cRSA
, rsa
, dmp1
);
493 DEF_OSSL_PKEY_BN(cRSA
, rsa
, dmq1
);
494 DEF_OSSL_PKEY_BN(cRSA
, rsa
, iqmp
);
496 rb_define_method(cRSA
, "params", ossl_rsa_get_params
, 0);
498 DefRSAConst(PKCS1_PADDING
);
499 DefRSAConst(SSLV23_PADDING
);
500 DefRSAConst(NO_PADDING
);
501 DefRSAConst(PKCS1_OAEP_PADDING
);
505 rb_define_method(cRSA, "blinding_on!", ossl_rsa_blinding_on, 0);
506 rb_define_method(cRSA, "blinding_off!", ossl_rsa_blinding_off, 0);
510 #else /* defined NO_RSA */
511 # warning >>> OpenSSL is compiled without RSA support <<<
515 rb_warning("OpenSSL is compiled without RSA support");