2 * Copyright (c) 2006 - 2007 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 RCSID("$Id: rsa.c 20466 2007-04-20 08:29:05Z lha $");
42 #include <krb5-types.h>
43 #include <rfc2459_asn1.h>
52 return RSA_new_method(NULL);
56 RSA_new_method(ENGINE *engine)
60 rsa = calloc(1, sizeof(*rsa));
67 ENGINE_up_ref(engine);
70 rsa->engine = ENGINE_get_default_RSA();
74 rsa->meth = ENGINE_get_RSA(rsa->engine);
75 if (rsa->meth == NULL) {
76 ENGINE_finish(engine);
82 if (rsa->meth == NULL)
83 rsa->meth = rk_UNCONST(RSA_get_default_method());
85 (*rsa->meth->init)(rsa);
94 if (rsa->references <= 0)
97 if (--rsa->references > 0)
100 (*rsa->meth->finish)(rsa);
103 ENGINE_finish(rsa->engine);
105 #define free_if(f) if (f) { BN_free(f); }
116 memset(rsa, 0, sizeof(*rsa));
123 return ++rsa->references;
127 RSA_get_method(const RSA *rsa)
133 RSA_set_method(RSA *rsa, const RSA_METHOD *method)
135 (*rsa->meth->finish)(rsa);
138 ENGINE_finish(rsa->engine);
143 (*rsa->meth->init)(rsa);
148 RSA_set_app_data(RSA *rsa, void *arg)
150 rsa->ex_data.sk = arg;
155 RSA_get_app_data(RSA *rsa)
157 return rsa->ex_data.sk;
161 RSA_check_key(const RSA *key)
163 static const unsigned char inbuf[] = "hello, world!";
164 RSA *rsa = rk_UNCONST(key);
169 * XXX I have no clue how to implement this w/o a bignum library.
170 * Well, when we have a RSA key pair, we can try to encrypt/sign
171 * and then decrypt/verify.
174 if ((rsa->d == NULL || rsa->n == NULL) &&
175 (rsa->p == NULL || rsa->q || rsa->dmp1 == NULL || rsa->dmq1 == NULL || rsa->iqmp == NULL))
178 buffer = malloc(RSA_size(rsa));
182 ret = RSA_private_encrypt(sizeof(inbuf), inbuf, buffer,
183 rsa, RSA_PKCS1_PADDING);
189 ret = RSA_public_decrypt(ret, buffer, buffer,
190 rsa, RSA_PKCS1_PADDING);
196 if (ret == sizeof(inbuf) && memcmp(buffer, inbuf, sizeof(inbuf)) == 0) {
205 RSA_size(const RSA *rsa)
207 return BN_num_bytes(rsa->n);
210 #define RSAFUNC(name, body) \
212 name(int flen,const unsigned char* f, unsigned char* t, RSA* r, int p){\
216 RSAFUNC(RSA_public_encrypt, (r)->meth->rsa_pub_enc(flen, f, t, r, p))
217 RSAFUNC(RSA_public_decrypt, (r)->meth->rsa_pub_dec(flen, f, t, r, p))
218 RSAFUNC(RSA_private_encrypt, (r)->meth->rsa_priv_enc(flen, f, t, r, p))
219 RSAFUNC(RSA_private_decrypt, (r)->meth->rsa_priv_dec(flen, f, t, r, p))
223 RSA_sign(int type, const unsigned char *from, unsigned int flen,
224 unsigned char *to, unsigned int *tlen, RSA *rsa)
230 RSA_verify(int type, const unsigned char *from, unsigned int flen,
231 unsigned char *to, unsigned int tlen, RSA *rsa)
237 * A NULL RSA_METHOD that returns failure for all operations. This is
238 * used as the default RSA method if we don't have any native
242 static RSAFUNC(null_rsa_public_encrypt, -1)
243 static RSAFUNC(null_rsa_public_decrypt, -1)
244 static RSAFUNC(null_rsa_private_encrypt, -1)
245 static RSAFUNC(null_rsa_private_decrypt, -1)
252 RSA_generate_key_ex(RSA *r, int bits, BIGNUM *e, BN_GENCB *cb)
254 if (r->meth->rsa_keygen)
255 return (*r->meth->rsa_keygen)(r, bits, e, cb);
265 null_rsa_init(RSA *rsa)
271 null_rsa_finish(RSA *rsa)
276 static const RSA_METHOD rsa_null_method = {
278 null_rsa_public_encrypt,
279 null_rsa_public_decrypt,
280 null_rsa_private_encrypt,
281 null_rsa_private_decrypt,
293 RSA_null_method(void)
295 return &rsa_null_method;
298 extern const RSA_METHOD hc_rsa_imath_method;
299 static const RSA_METHOD *default_rsa_method = &hc_rsa_imath_method;
302 RSA_get_default_method(void)
304 return default_rsa_method;
308 RSA_set_default_method(const RSA_METHOD *meth)
310 default_rsa_method = meth;
318 heim_int2BN(const heim_integer *i)
322 bn = BN_bin2bn(i->data, i->length, NULL);
324 BN_set_negative(bn, i->negative);
329 bn2heim_int(BIGNUM *bn, heim_integer *integer)
331 integer->length = BN_num_bytes(bn);
332 integer->data = malloc(integer->length);
333 if (integer->data == NULL) {
337 BN_bn2bin(bn, integer->data);
338 integer->negative = BN_is_negative(bn);
344 d2i_RSAPrivateKey(RSA *rsa, const unsigned char **pp, size_t len)
351 ret = decode_RSAPrivateKey(*pp, len, &data, &size);
360 free_RSAPrivateKey(&data);
365 k->n = heim_int2BN(&data.modulus);
366 k->e = heim_int2BN(&data.publicExponent);
367 k->d = heim_int2BN(&data.privateExponent);
368 k->p = heim_int2BN(&data.prime1);
369 k->q = heim_int2BN(&data.prime2);
370 k->dmp1 = heim_int2BN(&data.exponent1);
371 k->dmq1 = heim_int2BN(&data.exponent2);
372 k->iqmp = heim_int2BN(&data.coefficient);
373 free_RSAPrivateKey(&data);
375 if (k->n == NULL || k->e == NULL || k->d == NULL || k->p == NULL ||
376 k->q == NULL || k->dmp1 == NULL || k->dmq1 == NULL || k->iqmp == NULL)
386 i2d_RSAPrivateKey(RSA *rsa, unsigned char **pp)
392 if (rsa->n == NULL || rsa->e == NULL || rsa->d == NULL || rsa->p == NULL ||
393 rsa->q == NULL || rsa->dmp1 == NULL || rsa->dmq1 == NULL ||
397 memset(&data, 0, sizeof(data));
399 ret = bn2heim_int(rsa->n, &data.modulus);
400 ret |= bn2heim_int(rsa->e, &data.publicExponent);
401 ret |= bn2heim_int(rsa->d, &data.privateExponent);
402 ret |= bn2heim_int(rsa->p, &data.prime1);
403 ret |= bn2heim_int(rsa->q, &data.prime2);
404 ret |= bn2heim_int(rsa->dmp1, &data.exponent1);
405 ret |= bn2heim_int(rsa->dmq1, &data.exponent2);
406 ret |= bn2heim_int(rsa->iqmp, &data.coefficient);
408 free_RSAPrivateKey(&data);
413 size = length_RSAPrivateKey(&data);
414 free_RSAPrivateKey(&data);
419 ASN1_MALLOC_ENCODE(RSAPrivateKey, p, len, &data, &size, ret);
420 free_RSAPrivateKey(&data);
426 memcpy(*pp, p, size);
436 i2d_RSAPublicKey(RSA *rsa, unsigned char **pp)
442 memset(&data, 0, sizeof(data));
444 if (bn2heim_int(rsa->n, &data.modulus) ||
445 bn2heim_int(rsa->e, &data.publicExponent))
447 free_RSAPublicKey(&data);
452 size = length_RSAPublicKey(&data);
453 free_RSAPublicKey(&data);
458 ASN1_MALLOC_ENCODE(RSAPublicKey, p, len, &data, &size, ret);
459 free_RSAPublicKey(&data);
465 memcpy(*pp, p, size);