2 * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include <krb5-types.h>
39 #include <rfc2459_asn1.h>
50 * @page page_rsa RSA - public-key cryptography
52 * RSA is named by its inventors (Ron Rivest, Adi Shamir, and Leonard
53 * Adleman) (published in 1977), patented expired in 21 September 2000.
56 * Speed for RSA in seconds
60 * operation performed each eteration sign, verify, encrypt, decrypt on a random bit pattern
64 * ltm: 3.79 (default in hcrypto)
69 * See the library functions here: @ref hcrypto_rsa
73 * Same as RSA_new_method() using NULL as engine.
75 * @return a newly allocated RSA object. Free with RSA_free().
77 * @ingroup hcrypto_rsa
83 return RSA_new_method(NULL
);
87 * Allocate a new RSA object using the engine, if NULL is specified as
88 * the engine, use the default RSA engine as returned by
89 * ENGINE_get_default_RSA().
91 * @param engine Specific what ENGINE RSA provider should be used.
93 * @return a newly allocated RSA object. Free with RSA_free().
95 * @ingroup hcrypto_rsa
99 RSA_new_method(ENGINE
*engine
)
103 rsa
= calloc(1, sizeof(*rsa
));
110 ENGINE_up_ref(engine
);
111 rsa
->engine
= engine
;
113 rsa
->engine
= ENGINE_get_default_RSA();
117 rsa
->meth
= ENGINE_get_RSA(rsa
->engine
);
118 if (rsa
->meth
== NULL
) {
119 ENGINE_finish(engine
);
125 if (rsa
->meth
== NULL
)
126 rsa
->meth
= rk_UNCONST(RSA_get_default_method());
128 (*rsa
->meth
->init
)(rsa
);
134 * Free an allocation RSA object.
136 * @param rsa the RSA object to free.
137 * @ingroup hcrypto_rsa
143 if (rsa
->references
<= 0)
146 if (--rsa
->references
> 0)
149 (*rsa
->meth
->finish
)(rsa
);
152 ENGINE_finish(rsa
->engine
);
154 #define free_if(f) if (f) { BN_free(f); }
165 memset(rsa
, 0, sizeof(*rsa
));
170 * Add an extra reference to the RSA object. The object should be free
171 * with RSA_free() to drop the reference.
173 * @param rsa the object to add reference counting too.
175 * @return the current reference count, can't safely be used except
176 * for debug printing.
178 * @ingroup hcrypto_rsa
184 return ++rsa
->references
;
188 * Return the RSA_METHOD used for this RSA object.
190 * @param rsa the object to get the method from.
192 * @return the method used for this RSA object.
194 * @ingroup hcrypto_rsa
198 RSA_get_method(const RSA
*rsa
)
204 * Set a new method for the RSA keypair.
206 * @param rsa rsa parameter.
207 * @param method the new method for the RSA parameter.
209 * @return 1 on success.
211 * @ingroup hcrypto_rsa
215 RSA_set_method(RSA
*rsa
, const RSA_METHOD
*method
)
217 (*rsa
->meth
->finish
)(rsa
);
220 ENGINE_finish(rsa
->engine
);
225 (*rsa
->meth
->init
)(rsa
);
230 * Set the application data for the RSA object.
232 * @param rsa the rsa object to set the parameter for
233 * @param arg the data object to store
235 * @return 1 on success.
237 * @ingroup hcrypto_rsa
241 RSA_set_app_data(RSA
*rsa
, void *arg
)
243 rsa
->ex_data
.sk
= arg
;
248 * Get the application data for the RSA object.
250 * @param rsa the rsa object to get the parameter for
252 * @return the data object
254 * @ingroup hcrypto_rsa
258 RSA_get_app_data(const RSA
*rsa
)
260 return rsa
->ex_data
.sk
;
264 RSA_check_key(const RSA
*key
)
266 static const unsigned char inbuf
[] = "hello, world!";
267 RSA
*rsa
= rk_UNCONST(key
);
272 * XXX I have no clue how to implement this w/o a bignum library.
273 * Well, when we have a RSA key pair, we can try to encrypt/sign
274 * and then decrypt/verify.
277 if ((rsa
->d
== NULL
|| rsa
->n
== NULL
) &&
278 (rsa
->p
== NULL
|| rsa
->q
|| rsa
->dmp1
== NULL
|| rsa
->dmq1
== NULL
|| rsa
->iqmp
== NULL
))
281 buffer
= malloc(RSA_size(rsa
));
285 ret
= RSA_private_encrypt(sizeof(inbuf
), inbuf
, buffer
,
286 rsa
, RSA_PKCS1_PADDING
);
292 ret
= RSA_public_decrypt(ret
, buffer
, buffer
,
293 rsa
, RSA_PKCS1_PADDING
);
299 if (ret
== sizeof(inbuf
) && ct_memcmp(buffer
, inbuf
, sizeof(inbuf
)) == 0) {
308 RSA_size(const RSA
*rsa
)
310 return BN_num_bytes(rsa
->n
);
313 #define RSAFUNC(name, body) \
315 name(int flen,const unsigned char* f, unsigned char* t, RSA* r, int p){\
319 RSAFUNC(RSA_public_encrypt
, (r
)->meth
->rsa_pub_enc(flen
, f
, t
, r
, p
))
320 RSAFUNC(RSA_public_decrypt
, (r
)->meth
->rsa_pub_dec(flen
, f
, t
, r
, p
))
321 RSAFUNC(RSA_private_encrypt
, (r
)->meth
->rsa_priv_enc(flen
, f
, t
, r
, p
))
322 RSAFUNC(RSA_private_decrypt
, (r
)->meth
->rsa_priv_dec(flen
, f
, t
, r
, p
))
324 static const heim_octet_string null_entry_oid
= { 2, rk_UNCONST("\x05\x00") };
326 static const unsigned sha1_oid_tree
[] = { 1, 3, 14, 3, 2, 26 };
327 static const AlgorithmIdentifier _signature_sha1_data
= {
328 { 6, rk_UNCONST(sha1_oid_tree
) }, rk_UNCONST(&null_entry_oid
)
330 static const unsigned sha256_oid_tree
[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
331 static const AlgorithmIdentifier _signature_sha256_data
= {
332 { 9, rk_UNCONST(sha256_oid_tree
) }, rk_UNCONST(&null_entry_oid
)
334 static const unsigned md5_oid_tree
[] = { 1, 2, 840, 113549, 2, 5 };
335 static const AlgorithmIdentifier _signature_md5_data
= {
336 { 6, rk_UNCONST(md5_oid_tree
) }, rk_UNCONST(&null_entry_oid
)
341 RSA_sign(int type
, const unsigned char *from
, unsigned int flen
,
342 unsigned char *to
, unsigned int *tlen
, RSA
*rsa
)
344 if (rsa
->meth
->rsa_sign
)
345 return rsa
->meth
->rsa_sign(type
, from
, flen
, to
, tlen
, rsa
);
347 if (rsa
->meth
->rsa_priv_enc
) {
348 heim_octet_string indata
;
353 memset(&di
, 0, sizeof(di
));
355 if (type
== NID_sha1
) {
356 di
.digestAlgorithm
= _signature_sha1_data
;
357 } else if (type
== NID_md5
) {
358 di
.digestAlgorithm
= _signature_md5_data
;
359 } else if (type
== NID_sha256
) {
360 di
.digestAlgorithm
= _signature_sha256_data
;
364 di
.digest
.data
= rk_UNCONST(from
);
365 di
.digest
.length
= flen
;
367 ASN1_MALLOC_ENCODE(DigestInfo
,
375 if (indata
.length
!= size
)
378 ret
= rsa
->meth
->rsa_priv_enc(indata
.length
, indata
.data
, to
,
379 rsa
, RSA_PKCS1_PADDING
);
394 RSA_verify(int type
, const unsigned char *from
, unsigned int flen
,
395 unsigned char *sigbuf
, unsigned int siglen
, RSA
*rsa
)
397 if (rsa
->meth
->rsa_verify
)
398 return rsa
->meth
->rsa_verify(type
, from
, flen
, sigbuf
, siglen
, rsa
);
400 if (rsa
->meth
->rsa_pub_dec
) {
401 const AlgorithmIdentifier
*digest_alg
;
407 data
= malloc(RSA_size(rsa
));
411 memset(&di
, 0, sizeof(di
));
413 ret
= rsa
->meth
->rsa_pub_dec(siglen
, sigbuf
, data
, rsa
, RSA_PKCS1_PADDING
);
419 ret2
= decode_DigestInfo(data
, ret
, &di
, &size
);
424 free_DigestInfo(&di
);
428 if (flen
!= di
.digest
.length
|| memcmp(di
.digest
.data
, from
, flen
) != 0) {
429 free_DigestInfo(&di
);
433 if (type
== NID_sha1
) {
434 digest_alg
= &_signature_sha1_data
;
435 } else if (type
== NID_md5
) {
436 digest_alg
= &_signature_md5_data
;
437 } else if (type
== NID_sha256
) {
438 digest_alg
= &_signature_sha256_data
;
440 free_DigestInfo(&di
);
444 ret
= der_heim_oid_cmp(&digest_alg
->algorithm
,
445 &di
.digestAlgorithm
.algorithm
);
446 free_DigestInfo(&di
);
457 * A NULL RSA_METHOD that returns failure for all operations. This is
458 * used as the default RSA method if we don't have any native
462 static RSAFUNC(null_rsa_public_encrypt
, -1)
463 static RSAFUNC(null_rsa_public_decrypt
, -1)
464 static RSAFUNC(null_rsa_private_encrypt
, -1)
465 static RSAFUNC(null_rsa_private_decrypt
, -1)
472 RSA_generate_key_ex(RSA
*r
, int bits
, BIGNUM
*e
, BN_GENCB
*cb
)
474 if (r
->meth
->rsa_keygen
)
475 return (*r
->meth
->rsa_keygen
)(r
, bits
, e
, cb
);
485 null_rsa_init(RSA
*rsa
)
491 null_rsa_finish(RSA
*rsa
)
496 static const RSA_METHOD rsa_null_method
= {
498 null_rsa_public_encrypt
,
499 null_rsa_public_decrypt
,
500 null_rsa_private_encrypt
,
501 null_rsa_private_decrypt
,
513 RSA_null_method(void)
515 return &rsa_null_method
;
518 extern const RSA_METHOD hc_rsa_gmp_method
;
519 extern const RSA_METHOD hc_rsa_imath_method
;
520 extern const RSA_METHOD hc_rsa_tfm_method
;
521 extern const RSA_METHOD hc_rsa_ltm_method
;
522 static const RSA_METHOD
*default_rsa_method
= &hc_rsa_ltm_method
;
526 RSA_get_default_method(void)
528 return default_rsa_method
;
532 RSA_set_default_method(const RSA_METHOD
*meth
)
534 default_rsa_method
= meth
;
542 d2i_RSAPrivateKey(RSA
*rsa
, const unsigned char **pp
, size_t len
)
549 ret
= decode_RSAPrivateKey(*pp
, len
, &data
, &size
);
558 free_RSAPrivateKey(&data
);
563 k
->n
= _hc_integer_to_BN(&data
.modulus
, NULL
);
564 k
->e
= _hc_integer_to_BN(&data
.publicExponent
, NULL
);
565 k
->d
= _hc_integer_to_BN(&data
.privateExponent
, NULL
);
566 k
->p
= _hc_integer_to_BN(&data
.prime1
, NULL
);
567 k
->q
= _hc_integer_to_BN(&data
.prime2
, NULL
);
568 k
->dmp1
= _hc_integer_to_BN(&data
.exponent1
, NULL
);
569 k
->dmq1
= _hc_integer_to_BN(&data
.exponent2
, NULL
);
570 k
->iqmp
= _hc_integer_to_BN(&data
.coefficient
, NULL
);
571 free_RSAPrivateKey(&data
);
573 if (k
->n
== NULL
|| k
->e
== NULL
|| k
->d
== NULL
|| k
->p
== NULL
||
574 k
->q
== NULL
|| k
->dmp1
== NULL
|| k
->dmq1
== NULL
|| k
->iqmp
== NULL
)
584 i2d_RSAPrivateKey(RSA
*rsa
, unsigned char **pp
)
590 if (rsa
->n
== NULL
|| rsa
->e
== NULL
|| rsa
->d
== NULL
|| rsa
->p
== NULL
||
591 rsa
->q
== NULL
|| rsa
->dmp1
== NULL
|| rsa
->dmq1
== NULL
||
595 memset(&data
, 0, sizeof(data
));
597 ret
= _hc_BN_to_integer(rsa
->n
, &data
.modulus
);
598 ret
|= _hc_BN_to_integer(rsa
->e
, &data
.publicExponent
);
599 ret
|= _hc_BN_to_integer(rsa
->d
, &data
.privateExponent
);
600 ret
|= _hc_BN_to_integer(rsa
->p
, &data
.prime1
);
601 ret
|= _hc_BN_to_integer(rsa
->q
, &data
.prime2
);
602 ret
|= _hc_BN_to_integer(rsa
->dmp1
, &data
.exponent1
);
603 ret
|= _hc_BN_to_integer(rsa
->dmq1
, &data
.exponent2
);
604 ret
|= _hc_BN_to_integer(rsa
->iqmp
, &data
.coefficient
);
606 free_RSAPrivateKey(&data
);
611 size
= length_RSAPrivateKey(&data
);
612 free_RSAPrivateKey(&data
);
617 ASN1_MALLOC_ENCODE(RSAPrivateKey
, p
, len
, &data
, &size
, ret
);
618 free_RSAPrivateKey(&data
);
624 memcpy(*pp
, p
, size
);
634 i2d_RSAPublicKey(RSA
*rsa
, unsigned char **pp
)
640 memset(&data
, 0, sizeof(data
));
642 if (_hc_BN_to_integer(rsa
->n
, &data
.modulus
) ||
643 _hc_BN_to_integer(rsa
->e
, &data
.publicExponent
))
645 free_RSAPublicKey(&data
);
650 size
= length_RSAPublicKey(&data
);
651 free_RSAPublicKey(&data
);
656 ASN1_MALLOC_ENCODE(RSAPublicKey
, p
, len
, &data
, &size
, ret
);
657 free_RSAPublicKey(&data
);
663 memcpy(*pp
, p
, size
);
673 d2i_RSAPublicKey(RSA
*rsa
, const unsigned char **pp
, size_t len
)
680 ret
= decode_RSAPublicKey(*pp
, len
, &data
, &size
);
689 free_RSAPublicKey(&data
);
694 k
->n
= _hc_integer_to_BN(&data
.modulus
, NULL
);
695 k
->e
= _hc_integer_to_BN(&data
.publicExponent
, NULL
);
697 free_RSAPublicKey(&data
);
699 if (k
->n
== NULL
|| k
->e
== NULL
) {