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
36 #include <krb5-types.h>
37 #include <rfc2459_asn1.h>
46 * @page page_rsa RSA - public-key cryptography
48 * RSA is named by its inventors (Ron Rivest, Adi Shamir, and Leonard
49 * Adleman) (published in 1977), patented expired in 21 September 2000.
52 * Speed for RSA in seconds
55 * same rsa keys (1024 and 2048)
56 * operation performed each eteration sign, verify, encrypt, decrypt on a random bit pattern
59 * =================================
60 * gmp: 0.73 6.60 44.80
62 * ltm: 3.79 20.74 105.41 (default in hcrypto)
63 * openssl: 4.04 11.90 82.59
64 * cdsa: 15.89 102.89 721.40
67 * See the library functions here: @ref hcrypto_rsa
71 * Same as RSA_new_method() using NULL as engine.
73 * @return a newly allocated RSA object. Free with RSA_free().
75 * @ingroup hcrypto_rsa
81 return RSA_new_method(NULL
);
85 * Allocate a new RSA object using the engine, if NULL is specified as
86 * the engine, use the default RSA engine as returned by
87 * ENGINE_get_default_RSA().
89 * @param engine Specific what ENGINE RSA provider should be used.
91 * @return a newly allocated RSA object. Free with RSA_free().
93 * @ingroup hcrypto_rsa
97 RSA_new_method(ENGINE
*engine
)
101 rsa
= calloc(1, sizeof(*rsa
));
108 ENGINE_up_ref(engine
);
109 rsa
->engine
= engine
;
111 rsa
->engine
= ENGINE_get_default_RSA();
115 rsa
->meth
= ENGINE_get_RSA(rsa
->engine
);
116 if (rsa
->meth
== NULL
) {
117 ENGINE_finish(engine
);
123 if (rsa
->meth
== NULL
)
124 rsa
->meth
= rk_UNCONST(RSA_get_default_method());
126 (*rsa
->meth
->init
)(rsa
);
132 * Free an allocation RSA object.
134 * @param rsa the RSA object to free.
135 * @ingroup hcrypto_rsa
141 if (rsa
->references
<= 0)
144 if (--rsa
->references
> 0)
147 (*rsa
->meth
->finish
)(rsa
);
150 ENGINE_finish(rsa
->engine
);
152 #define free_if(f) if (f) { BN_free(f); }
163 memset(rsa
, 0, sizeof(*rsa
));
168 * Add an extra reference to the RSA object. The object should be free
169 * with RSA_free() to drop the reference.
171 * @param rsa the object to add reference counting too.
173 * @return the current reference count, can't safely be used except
174 * for debug printing.
176 * @ingroup hcrypto_rsa
182 return ++rsa
->references
;
186 * Return the RSA_METHOD used for this RSA object.
188 * @param rsa the object to get the method from.
190 * @return the method used for this RSA object.
192 * @ingroup hcrypto_rsa
196 RSA_get_method(const RSA
*rsa
)
202 * Set a new method for the RSA keypair.
204 * @param rsa rsa parameter.
205 * @param method the new method for the RSA parameter.
207 * @return 1 on success.
209 * @ingroup hcrypto_rsa
213 RSA_set_method(RSA
*rsa
, const RSA_METHOD
*method
)
215 (*rsa
->meth
->finish
)(rsa
);
218 ENGINE_finish(rsa
->engine
);
223 (*rsa
->meth
->init
)(rsa
);
228 * Set the application data for the RSA object.
230 * @param rsa the rsa object to set the parameter for
231 * @param arg the data object to store
233 * @return 1 on success.
235 * @ingroup hcrypto_rsa
239 RSA_set_app_data(RSA
*rsa
, void *arg
)
241 rsa
->ex_data
.sk
= arg
;
246 * Get the application data for the RSA object.
248 * @param rsa the rsa object to get the parameter for
250 * @return the data object
252 * @ingroup hcrypto_rsa
256 RSA_get_app_data(const RSA
*rsa
)
258 return rsa
->ex_data
.sk
;
262 RSA_check_key(const RSA
*key
)
264 static const unsigned char inbuf
[] = "hello, world!";
265 RSA
*rsa
= rk_UNCONST(key
);
270 * XXX I have no clue how to implement this w/o a bignum library.
271 * Well, when we have a RSA key pair, we can try to encrypt/sign
272 * and then decrypt/verify.
275 if ((rsa
->d
== NULL
|| rsa
->n
== NULL
) &&
276 (rsa
->p
== NULL
|| rsa
->q
|| rsa
->dmp1
== NULL
|| rsa
->dmq1
== NULL
|| rsa
->iqmp
== NULL
))
279 buffer
= malloc(RSA_size(rsa
));
283 ret
= RSA_private_encrypt(sizeof(inbuf
), inbuf
, buffer
,
284 rsa
, RSA_PKCS1_PADDING
);
290 ret
= RSA_public_decrypt(ret
, buffer
, buffer
,
291 rsa
, RSA_PKCS1_PADDING
);
297 if (ret
== sizeof(inbuf
) && ct_memcmp(buffer
, inbuf
, sizeof(inbuf
)) == 0) {
306 RSA_size(const RSA
*rsa
)
308 return BN_num_bytes(rsa
->n
);
311 #define RSAFUNC(name, body) \
313 name(int flen,const unsigned char* f, unsigned char* t, RSA* r, int p){\
317 RSAFUNC(RSA_public_encrypt
, (r
)->meth
->rsa_pub_enc(flen
, f
, t
, r
, p
))
318 RSAFUNC(RSA_public_decrypt
, (r
)->meth
->rsa_pub_dec(flen
, f
, t
, r
, p
))
319 RSAFUNC(RSA_private_encrypt
, (r
)->meth
->rsa_priv_enc(flen
, f
, t
, r
, p
))
320 RSAFUNC(RSA_private_decrypt
, (r
)->meth
->rsa_priv_dec(flen
, f
, t
, r
, p
))
322 static const heim_octet_string null_entry_oid
= { 2, rk_UNCONST("\x05\x00") };
324 static const unsigned sha1_oid_tree
[] = { 1, 3, 14, 3, 2, 26 };
325 static const AlgorithmIdentifier _signature_sha1_data
= {
326 { 6, rk_UNCONST(sha1_oid_tree
) }, rk_UNCONST(&null_entry_oid
)
328 static const unsigned sha256_oid_tree
[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
329 static const AlgorithmIdentifier _signature_sha256_data
= {
330 { 9, rk_UNCONST(sha256_oid_tree
) }, rk_UNCONST(&null_entry_oid
)
332 static const unsigned md5_oid_tree
[] = { 1, 2, 840, 113549, 2, 5 };
333 static const AlgorithmIdentifier _signature_md5_data
= {
334 { 6, rk_UNCONST(md5_oid_tree
) }, rk_UNCONST(&null_entry_oid
)
339 RSA_sign(int type
, const unsigned char *from
, unsigned int flen
,
340 unsigned char *to
, unsigned int *tlen
, RSA
*rsa
)
342 if (rsa
->meth
->rsa_sign
)
343 return rsa
->meth
->rsa_sign(type
, from
, flen
, to
, tlen
, rsa
);
345 if (rsa
->meth
->rsa_priv_enc
) {
346 heim_octet_string indata
;
351 memset(&di
, 0, sizeof(di
));
353 if (type
== NID_sha1
) {
354 di
.digestAlgorithm
= _signature_sha1_data
;
355 } else if (type
== NID_md5
) {
356 di
.digestAlgorithm
= _signature_md5_data
;
357 } else if (type
== NID_sha256
) {
358 di
.digestAlgorithm
= _signature_sha256_data
;
362 di
.digest
.data
= rk_UNCONST(from
);
363 di
.digest
.length
= flen
;
365 ASN1_MALLOC_ENCODE(DigestInfo
,
373 if (indata
.length
!= size
)
376 ret
= rsa
->meth
->rsa_priv_enc(indata
.length
, indata
.data
, to
,
377 rsa
, RSA_PKCS1_PADDING
);
392 RSA_verify(int type
, const unsigned char *from
, unsigned int flen
,
393 unsigned char *sigbuf
, unsigned int siglen
, RSA
*rsa
)
395 if (rsa
->meth
->rsa_verify
)
396 return rsa
->meth
->rsa_verify(type
, from
, flen
, sigbuf
, siglen
, rsa
);
398 if (rsa
->meth
->rsa_pub_dec
) {
399 const AlgorithmIdentifier
*digest_alg
;
405 data
= malloc(RSA_size(rsa
));
409 memset(&di
, 0, sizeof(di
));
411 ret
= rsa
->meth
->rsa_pub_dec(siglen
, sigbuf
, data
, rsa
, RSA_PKCS1_PADDING
);
417 ret2
= decode_DigestInfo(data
, ret
, &di
, &size
);
422 free_DigestInfo(&di
);
426 if (flen
!= di
.digest
.length
|| memcmp(di
.digest
.data
, from
, flen
) != 0) {
427 free_DigestInfo(&di
);
431 if (type
== NID_sha1
) {
432 digest_alg
= &_signature_sha1_data
;
433 } else if (type
== NID_md5
) {
434 digest_alg
= &_signature_md5_data
;
435 } else if (type
== NID_sha256
) {
436 digest_alg
= &_signature_sha256_data
;
438 free_DigestInfo(&di
);
442 ret
= der_heim_oid_cmp(&digest_alg
->algorithm
,
443 &di
.digestAlgorithm
.algorithm
);
444 free_DigestInfo(&di
);
455 * A NULL RSA_METHOD that returns failure for all operations. This is
456 * used as the default RSA method if we don't have any native
460 static RSAFUNC(null_rsa_public_encrypt
, -1)
461 static RSAFUNC(null_rsa_public_decrypt
, -1)
462 static RSAFUNC(null_rsa_private_encrypt
, -1)
463 static RSAFUNC(null_rsa_private_decrypt
, -1)
470 RSA_generate_key_ex(RSA
*r
, int bits
, BIGNUM
*e
, BN_GENCB
*cb
)
472 if (r
->meth
->rsa_keygen
)
473 return (*r
->meth
->rsa_keygen
)(r
, bits
, e
, cb
);
483 null_rsa_init(RSA
*rsa
)
489 null_rsa_finish(RSA
*rsa
)
494 static const RSA_METHOD rsa_null_method
= {
496 null_rsa_public_encrypt
,
497 null_rsa_public_decrypt
,
498 null_rsa_private_encrypt
,
499 null_rsa_private_decrypt
,
512 RSA_null_method(void)
514 return &rsa_null_method
;
517 extern const RSA_METHOD hc_rsa_gmp_method
;
518 extern const RSA_METHOD hc_rsa_tfm_method
;
519 extern const RSA_METHOD hc_rsa_ltm_method
;
520 static const RSA_METHOD
*default_rsa_method
= &hc_rsa_ltm_method
;
524 RSA_get_default_method(void)
526 return default_rsa_method
;
530 RSA_set_default_method(const RSA_METHOD
*meth
)
532 default_rsa_method
= meth
;
540 d2i_RSAPrivateKey(RSA
*rsa
, const unsigned char **pp
, size_t len
)
547 ret
= decode_RSAPrivateKey(*pp
, len
, &data
, &size
);
556 free_RSAPrivateKey(&data
);
561 k
->n
= _hc_integer_to_BN(&data
.modulus
, NULL
);
562 k
->e
= _hc_integer_to_BN(&data
.publicExponent
, NULL
);
563 k
->d
= _hc_integer_to_BN(&data
.privateExponent
, NULL
);
564 k
->p
= _hc_integer_to_BN(&data
.prime1
, NULL
);
565 k
->q
= _hc_integer_to_BN(&data
.prime2
, NULL
);
566 k
->dmp1
= _hc_integer_to_BN(&data
.exponent1
, NULL
);
567 k
->dmq1
= _hc_integer_to_BN(&data
.exponent2
, NULL
);
568 k
->iqmp
= _hc_integer_to_BN(&data
.coefficient
, NULL
);
569 free_RSAPrivateKey(&data
);
571 if (k
->n
== NULL
|| k
->e
== NULL
|| k
->d
== NULL
|| k
->p
== NULL
||
572 k
->q
== NULL
|| k
->dmp1
== NULL
|| k
->dmq1
== NULL
|| k
->iqmp
== NULL
)
582 i2d_RSAPrivateKey(RSA
*rsa
, unsigned char **pp
)
588 if (rsa
->n
== NULL
|| rsa
->e
== NULL
|| rsa
->d
== NULL
|| rsa
->p
== NULL
||
589 rsa
->q
== NULL
|| rsa
->dmp1
== NULL
|| rsa
->dmq1
== NULL
||
593 memset(&data
, 0, sizeof(data
));
595 ret
= _hc_BN_to_integer(rsa
->n
, &data
.modulus
);
596 ret
|= _hc_BN_to_integer(rsa
->e
, &data
.publicExponent
);
597 ret
|= _hc_BN_to_integer(rsa
->d
, &data
.privateExponent
);
598 ret
|= _hc_BN_to_integer(rsa
->p
, &data
.prime1
);
599 ret
|= _hc_BN_to_integer(rsa
->q
, &data
.prime2
);
600 ret
|= _hc_BN_to_integer(rsa
->dmp1
, &data
.exponent1
);
601 ret
|= _hc_BN_to_integer(rsa
->dmq1
, &data
.exponent2
);
602 ret
|= _hc_BN_to_integer(rsa
->iqmp
, &data
.coefficient
);
604 free_RSAPrivateKey(&data
);
609 size
= length_RSAPrivateKey(&data
);
610 free_RSAPrivateKey(&data
);
615 ASN1_MALLOC_ENCODE(RSAPrivateKey
, p
, len
, &data
, &size
, ret
);
616 free_RSAPrivateKey(&data
);
622 memcpy(*pp
, p
, size
);
632 i2d_RSAPublicKey(RSA
*rsa
, unsigned char **pp
)
638 memset(&data
, 0, sizeof(data
));
640 if (_hc_BN_to_integer(rsa
->n
, &data
.modulus
) ||
641 _hc_BN_to_integer(rsa
->e
, &data
.publicExponent
))
643 free_RSAPublicKey(&data
);
648 size
= length_RSAPublicKey(&data
);
649 free_RSAPublicKey(&data
);
654 ASN1_MALLOC_ENCODE(RSAPublicKey
, p
, len
, &data
, &size
, ret
);
655 free_RSAPublicKey(&data
);
661 memcpy(*pp
, p
, size
);
671 d2i_RSAPublicKey(RSA
*rsa
, const unsigned char **pp
, size_t len
)
678 ret
= decode_RSAPublicKey(*pp
, len
, &data
, &size
);
687 free_RSAPublicKey(&data
);
692 k
->n
= _hc_integer_to_BN(&data
.modulus
, NULL
);
693 k
->e
= _hc_integer_to_BN(&data
.publicExponent
, NULL
);
695 free_RSAPublicKey(&data
);
697 if (k
->n
== NULL
|| k
->e
== NULL
) {