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
59 * same rsa keys (1024 and 2048)
60 * operation performed each eteration sign, verify, encrypt, decrypt on a random bit pattern
63 * =================================
64 * gmp: 0.73 6.60 44.80
66 * ltm: 3.79 20.74 105.41 (default in hcrypto)
67 * openssl: 4.04 11.90 82.59
68 * cdsa: 15.89 102.89 721.40
71 * See the library functions here: @ref hcrypto_rsa
75 * Same as RSA_new_method() using NULL as engine.
77 * @return a newly allocated RSA object. Free with RSA_free().
79 * @ingroup hcrypto_rsa
85 return RSA_new_method(NULL
);
89 * Allocate a new RSA object using the engine, if NULL is specified as
90 * the engine, use the default RSA engine as returned by
91 * ENGINE_get_default_RSA().
93 * @param engine Specific what ENGINE RSA provider should be used.
95 * @return a newly allocated RSA object. Free with RSA_free().
97 * @ingroup hcrypto_rsa
101 RSA_new_method(ENGINE
*engine
)
105 rsa
= calloc(1, sizeof(*rsa
));
112 ENGINE_up_ref(engine
);
113 rsa
->engine
= engine
;
115 rsa
->engine
= ENGINE_get_default_RSA();
119 rsa
->meth
= ENGINE_get_RSA(rsa
->engine
);
120 if (rsa
->meth
== NULL
) {
121 ENGINE_finish(engine
);
127 if (rsa
->meth
== NULL
)
128 rsa
->meth
= rk_UNCONST(RSA_get_default_method());
130 (*rsa
->meth
->init
)(rsa
);
136 * Free an allocation RSA object.
138 * @param rsa the RSA object to free.
139 * @ingroup hcrypto_rsa
145 if (rsa
->references
<= 0)
148 if (--rsa
->references
> 0)
151 (*rsa
->meth
->finish
)(rsa
);
154 ENGINE_finish(rsa
->engine
);
156 #define free_if(f) if (f) { BN_free(f); }
167 memset(rsa
, 0, sizeof(*rsa
));
172 * Add an extra reference to the RSA object. The object should be free
173 * with RSA_free() to drop the reference.
175 * @param rsa the object to add reference counting too.
177 * @return the current reference count, can't safely be used except
178 * for debug printing.
180 * @ingroup hcrypto_rsa
186 return ++rsa
->references
;
190 * Return the RSA_METHOD used for this RSA object.
192 * @param rsa the object to get the method from.
194 * @return the method used for this RSA object.
196 * @ingroup hcrypto_rsa
200 RSA_get_method(const RSA
*rsa
)
206 * Set a new method for the RSA keypair.
208 * @param rsa rsa parameter.
209 * @param method the new method for the RSA parameter.
211 * @return 1 on success.
213 * @ingroup hcrypto_rsa
217 RSA_set_method(RSA
*rsa
, const RSA_METHOD
*method
)
219 (*rsa
->meth
->finish
)(rsa
);
222 ENGINE_finish(rsa
->engine
);
227 (*rsa
->meth
->init
)(rsa
);
232 * Set the application data for the RSA object.
234 * @param rsa the rsa object to set the parameter for
235 * @param arg the data object to store
237 * @return 1 on success.
239 * @ingroup hcrypto_rsa
243 RSA_set_app_data(RSA
*rsa
, void *arg
)
245 rsa
->ex_data
.sk
= arg
;
250 * Get the application data for the RSA object.
252 * @param rsa the rsa object to get the parameter for
254 * @return the data object
256 * @ingroup hcrypto_rsa
260 RSA_get_app_data(const RSA
*rsa
)
262 return rsa
->ex_data
.sk
;
266 RSA_check_key(const RSA
*key
)
268 static const unsigned char inbuf
[] = "hello, world!";
269 RSA
*rsa
= rk_UNCONST(key
);
274 * XXX I have no clue how to implement this w/o a bignum library.
275 * Well, when we have a RSA key pair, we can try to encrypt/sign
276 * and then decrypt/verify.
279 if ((rsa
->d
== NULL
|| rsa
->n
== NULL
) &&
280 (rsa
->p
== NULL
|| rsa
->q
|| rsa
->dmp1
== NULL
|| rsa
->dmq1
== NULL
|| rsa
->iqmp
== NULL
))
283 buffer
= malloc(RSA_size(rsa
));
287 ret
= RSA_private_encrypt(sizeof(inbuf
), inbuf
, buffer
,
288 rsa
, RSA_PKCS1_PADDING
);
294 ret
= RSA_public_decrypt(ret
, buffer
, buffer
,
295 rsa
, RSA_PKCS1_PADDING
);
301 if (ret
== sizeof(inbuf
) && ct_memcmp(buffer
, inbuf
, sizeof(inbuf
)) == 0) {
310 RSA_size(const RSA
*rsa
)
312 return BN_num_bytes(rsa
->n
);
315 #define RSAFUNC(name, body) \
317 name(int flen,const unsigned char* f, unsigned char* t, RSA* r, int p){\
321 RSAFUNC(RSA_public_encrypt
, (r
)->meth
->rsa_pub_enc(flen
, f
, t
, r
, p
))
322 RSAFUNC(RSA_public_decrypt
, (r
)->meth
->rsa_pub_dec(flen
, f
, t
, r
, p
))
323 RSAFUNC(RSA_private_encrypt
, (r
)->meth
->rsa_priv_enc(flen
, f
, t
, r
, p
))
324 RSAFUNC(RSA_private_decrypt
, (r
)->meth
->rsa_priv_dec(flen
, f
, t
, r
, p
))
326 static const heim_octet_string null_entry_oid
= { 2, rk_UNCONST("\x05\x00") };
328 static const unsigned sha1_oid_tree
[] = { 1, 3, 14, 3, 2, 26 };
329 static const AlgorithmIdentifier _signature_sha1_data
= {
330 { 6, rk_UNCONST(sha1_oid_tree
) }, rk_UNCONST(&null_entry_oid
)
332 static const unsigned sha256_oid_tree
[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
333 static const AlgorithmIdentifier _signature_sha256_data
= {
334 { 9, rk_UNCONST(sha256_oid_tree
) }, rk_UNCONST(&null_entry_oid
)
336 static const unsigned md5_oid_tree
[] = { 1, 2, 840, 113549, 2, 5 };
337 static const AlgorithmIdentifier _signature_md5_data
= {
338 { 6, rk_UNCONST(md5_oid_tree
) }, rk_UNCONST(&null_entry_oid
)
343 RSA_sign(int type
, const unsigned char *from
, unsigned int flen
,
344 unsigned char *to
, unsigned int *tlen
, RSA
*rsa
)
346 if (rsa
->meth
->rsa_sign
)
347 return rsa
->meth
->rsa_sign(type
, from
, flen
, to
, tlen
, rsa
);
349 if (rsa
->meth
->rsa_priv_enc
) {
350 heim_octet_string indata
;
355 memset(&di
, 0, sizeof(di
));
357 if (type
== NID_sha1
) {
358 di
.digestAlgorithm
= _signature_sha1_data
;
359 } else if (type
== NID_md5
) {
360 di
.digestAlgorithm
= _signature_md5_data
;
361 } else if (type
== NID_sha256
) {
362 di
.digestAlgorithm
= _signature_sha256_data
;
366 di
.digest
.data
= rk_UNCONST(from
);
367 di
.digest
.length
= flen
;
369 ASN1_MALLOC_ENCODE(DigestInfo
,
377 if (indata
.length
!= size
)
380 ret
= rsa
->meth
->rsa_priv_enc(indata
.length
, indata
.data
, to
,
381 rsa
, RSA_PKCS1_PADDING
);
396 RSA_verify(int type
, const unsigned char *from
, unsigned int flen
,
397 unsigned char *sigbuf
, unsigned int siglen
, RSA
*rsa
)
399 if (rsa
->meth
->rsa_verify
)
400 return rsa
->meth
->rsa_verify(type
, from
, flen
, sigbuf
, siglen
, rsa
);
402 if (rsa
->meth
->rsa_pub_dec
) {
403 const AlgorithmIdentifier
*digest_alg
;
409 data
= malloc(RSA_size(rsa
));
413 memset(&di
, 0, sizeof(di
));
415 ret
= rsa
->meth
->rsa_pub_dec(siglen
, sigbuf
, data
, rsa
, RSA_PKCS1_PADDING
);
421 ret2
= decode_DigestInfo(data
, ret
, &di
, &size
);
426 free_DigestInfo(&di
);
430 if (flen
!= di
.digest
.length
|| memcmp(di
.digest
.data
, from
, flen
) != 0) {
431 free_DigestInfo(&di
);
435 if (type
== NID_sha1
) {
436 digest_alg
= &_signature_sha1_data
;
437 } else if (type
== NID_md5
) {
438 digest_alg
= &_signature_md5_data
;
439 } else if (type
== NID_sha256
) {
440 digest_alg
= &_signature_sha256_data
;
442 free_DigestInfo(&di
);
446 ret
= der_heim_oid_cmp(&digest_alg
->algorithm
,
447 &di
.digestAlgorithm
.algorithm
);
448 free_DigestInfo(&di
);
459 * A NULL RSA_METHOD that returns failure for all operations. This is
460 * used as the default RSA method if we don't have any native
464 static RSAFUNC(null_rsa_public_encrypt
, -1)
465 static RSAFUNC(null_rsa_public_decrypt
, -1)
466 static RSAFUNC(null_rsa_private_encrypt
, -1)
467 static RSAFUNC(null_rsa_private_decrypt
, -1)
474 RSA_generate_key_ex(RSA
*r
, int bits
, BIGNUM
*e
, BN_GENCB
*cb
)
476 if (r
->meth
->rsa_keygen
)
477 return (*r
->meth
->rsa_keygen
)(r
, bits
, e
, cb
);
487 null_rsa_init(RSA
*rsa
)
493 null_rsa_finish(RSA
*rsa
)
498 static const RSA_METHOD rsa_null_method
= {
500 null_rsa_public_encrypt
,
501 null_rsa_public_decrypt
,
502 null_rsa_private_encrypt
,
503 null_rsa_private_decrypt
,
516 RSA_null_method(void)
518 return &rsa_null_method
;
521 extern const RSA_METHOD hc_rsa_gmp_method
;
522 extern const RSA_METHOD hc_rsa_tfm_method
;
523 extern const RSA_METHOD hc_rsa_ltm_method
;
524 static const RSA_METHOD
*default_rsa_method
= &hc_rsa_ltm_method
;
528 RSA_get_default_method(void)
530 return default_rsa_method
;
534 RSA_set_default_method(const RSA_METHOD
*meth
)
536 default_rsa_method
= meth
;
544 d2i_RSAPrivateKey(RSA
*rsa
, const unsigned char **pp
, size_t len
)
551 ret
= decode_RSAPrivateKey(*pp
, len
, &data
, &size
);
560 free_RSAPrivateKey(&data
);
565 k
->n
= _hc_integer_to_BN(&data
.modulus
, NULL
);
566 k
->e
= _hc_integer_to_BN(&data
.publicExponent
, NULL
);
567 k
->d
= _hc_integer_to_BN(&data
.privateExponent
, NULL
);
568 k
->p
= _hc_integer_to_BN(&data
.prime1
, NULL
);
569 k
->q
= _hc_integer_to_BN(&data
.prime2
, NULL
);
570 k
->dmp1
= _hc_integer_to_BN(&data
.exponent1
, NULL
);
571 k
->dmq1
= _hc_integer_to_BN(&data
.exponent2
, NULL
);
572 k
->iqmp
= _hc_integer_to_BN(&data
.coefficient
, NULL
);
573 free_RSAPrivateKey(&data
);
575 if (k
->n
== NULL
|| k
->e
== NULL
|| k
->d
== NULL
|| k
->p
== NULL
||
576 k
->q
== NULL
|| k
->dmp1
== NULL
|| k
->dmq1
== NULL
|| k
->iqmp
== NULL
)
586 i2d_RSAPrivateKey(RSA
*rsa
, unsigned char **pp
)
592 if (rsa
->n
== NULL
|| rsa
->e
== NULL
|| rsa
->d
== NULL
|| rsa
->p
== NULL
||
593 rsa
->q
== NULL
|| rsa
->dmp1
== NULL
|| rsa
->dmq1
== NULL
||
597 memset(&data
, 0, sizeof(data
));
599 ret
= _hc_BN_to_integer(rsa
->n
, &data
.modulus
);
600 ret
|= _hc_BN_to_integer(rsa
->e
, &data
.publicExponent
);
601 ret
|= _hc_BN_to_integer(rsa
->d
, &data
.privateExponent
);
602 ret
|= _hc_BN_to_integer(rsa
->p
, &data
.prime1
);
603 ret
|= _hc_BN_to_integer(rsa
->q
, &data
.prime2
);
604 ret
|= _hc_BN_to_integer(rsa
->dmp1
, &data
.exponent1
);
605 ret
|= _hc_BN_to_integer(rsa
->dmq1
, &data
.exponent2
);
606 ret
|= _hc_BN_to_integer(rsa
->iqmp
, &data
.coefficient
);
608 free_RSAPrivateKey(&data
);
613 size
= length_RSAPrivateKey(&data
);
614 free_RSAPrivateKey(&data
);
619 ASN1_MALLOC_ENCODE(RSAPrivateKey
, p
, len
, &data
, &size
, ret
);
620 free_RSAPrivateKey(&data
);
626 memcpy(*pp
, p
, size
);
636 i2d_RSAPublicKey(RSA
*rsa
, unsigned char **pp
)
642 memset(&data
, 0, sizeof(data
));
644 if (_hc_BN_to_integer(rsa
->n
, &data
.modulus
) ||
645 _hc_BN_to_integer(rsa
->e
, &data
.publicExponent
))
647 free_RSAPublicKey(&data
);
652 size
= length_RSAPublicKey(&data
);
653 free_RSAPublicKey(&data
);
658 ASN1_MALLOC_ENCODE(RSAPublicKey
, p
, len
, &data
, &size
, ret
);
659 free_RSAPublicKey(&data
);
665 memcpy(*pp
, p
, size
);
675 d2i_RSAPublicKey(RSA
*rsa
, const unsigned char **pp
, size_t len
)
682 ret
= decode_RSAPublicKey(*pp
, len
, &data
, &size
);
691 free_RSAPublicKey(&data
);
696 k
->n
= _hc_integer_to_BN(&data
.modulus
, NULL
);
697 k
->e
= _hc_integer_to_BN(&data
.publicExponent
, NULL
);
699 free_RSAPublicKey(&data
);
701 if (k
->n
== NULL
|| k
->e
== NULL
) {