x
[heimdal.git] / lib / hcrypto / rsa.c
blob15656a92ee65b23c1d077dc00a732a756dd514f9
1 /*
2 * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
31 * SUCH DAMAGE.
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
38 RCSID("$Id$");
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <krb5-types.h>
43 #include <rfc2459_asn1.h>
45 #include <rsa.h>
47 #include <roken.h>
49 RSA *
50 RSA_new(void)
52 return RSA_new_method(NULL);
55 RSA *
56 RSA_new_method(ENGINE *engine)
58 RSA *rsa;
60 rsa = calloc(1, sizeof(*rsa));
61 if (rsa == NULL)
62 return NULL;
64 rsa->references = 1;
66 if (engine) {
67 ENGINE_up_ref(engine);
68 rsa->engine = engine;
69 } else {
70 rsa->engine = ENGINE_get_default_RSA();
73 if (rsa->engine) {
74 rsa->meth = ENGINE_get_RSA(rsa->engine);
75 if (rsa->meth == NULL) {
76 ENGINE_finish(engine);
77 free(rsa);
78 return 0;
82 if (rsa->meth == NULL)
83 rsa->meth = rk_UNCONST(RSA_get_default_method());
85 (*rsa->meth->init)(rsa);
87 return rsa;
91 void
92 RSA_free(RSA *rsa)
94 if (rsa->references <= 0)
95 abort();
97 if (--rsa->references > 0)
98 return;
100 (*rsa->meth->finish)(rsa);
102 if (rsa->engine)
103 ENGINE_finish(rsa->engine);
105 #define free_if(f) if (f) { BN_free(f); }
106 free_if(rsa->n);
107 free_if(rsa->e);
108 free_if(rsa->d);
109 free_if(rsa->p);
110 free_if(rsa->q);
111 free_if(rsa->dmp1);
112 free_if(rsa->dmq1);
113 free_if(rsa->iqmp);
114 #undef free_if
116 memset(rsa, 0, sizeof(*rsa));
117 free(rsa);
121 RSA_up_ref(RSA *rsa)
123 return ++rsa->references;
126 const RSA_METHOD *
127 RSA_get_method(const RSA *rsa)
129 return rsa->meth;
133 RSA_set_method(RSA *rsa, const RSA_METHOD *method)
135 (*rsa->meth->finish)(rsa);
137 if (rsa->engine) {
138 ENGINE_finish(rsa->engine);
139 rsa->engine = NULL;
142 rsa->meth = method;
143 (*rsa->meth->init)(rsa);
144 return 1;
148 RSA_set_app_data(RSA *rsa, void *arg)
150 rsa->ex_data.sk = arg;
151 return 1;
154 void *
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);
165 void *buffer;
166 int ret;
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))
176 return 0;
178 buffer = malloc(RSA_size(rsa));
179 if (buffer == NULL)
180 return 0;
182 ret = RSA_private_encrypt(sizeof(inbuf), inbuf, buffer,
183 rsa, RSA_PKCS1_PADDING);
184 if (ret == -1) {
185 free(buffer);
186 return 0;
189 ret = RSA_public_decrypt(ret, buffer, buffer,
190 rsa, RSA_PKCS1_PADDING);
191 if (ret == -1) {
192 free(buffer);
193 return 0;
196 if (ret == sizeof(inbuf) && memcmp(buffer, inbuf, sizeof(inbuf)) == 0) {
197 free(buffer);
198 return 1;
200 free(buffer);
201 return 0;
205 RSA_size(const RSA *rsa)
207 return BN_num_bytes(rsa->n);
210 #define RSAFUNC(name, body) \
211 int \
212 name(int flen,const unsigned char* f, unsigned char* t, RSA* r, int p){\
213 return body; \
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))
221 /* XXX */
223 RSA_sign(int type, const unsigned char *from, unsigned int flen,
224 unsigned char *to, unsigned int *tlen, RSA *rsa)
226 return -1;
230 RSA_verify(int type, const unsigned char *from, unsigned int flen,
231 unsigned char *to, unsigned int tlen, RSA *rsa)
233 return -1;
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
239 * support.
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);
256 return 0;
264 static int
265 null_rsa_init(RSA *rsa)
267 return 1;
270 static int
271 null_rsa_finish(RSA *rsa)
273 return 1;
276 static const RSA_METHOD rsa_null_method = {
277 "hcrypto null RSA",
278 null_rsa_public_encrypt,
279 null_rsa_public_decrypt,
280 null_rsa_private_encrypt,
281 null_rsa_private_decrypt,
282 NULL,
283 NULL,
284 null_rsa_init,
285 null_rsa_finish,
287 NULL,
288 NULL,
289 NULL
292 const RSA_METHOD *
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;
301 const RSA_METHOD *
302 RSA_get_default_method(void)
304 return default_rsa_method;
307 void
308 RSA_set_default_method(const RSA_METHOD *meth)
310 default_rsa_method = meth;
317 static BIGNUM *
318 heim_int2BN(const heim_integer *i)
320 BIGNUM *bn;
322 bn = BN_bin2bn(i->data, i->length, NULL);
323 if (bn)
324 BN_set_negative(bn, i->negative);
325 return bn;
328 static int
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) {
334 integer->length = 0;
335 return ENOMEM;
337 BN_bn2bin(bn, integer->data);
338 integer->negative = BN_is_negative(bn);
339 return 0;
343 RSA *
344 d2i_RSAPrivateKey(RSA *rsa, const unsigned char **pp, size_t len)
346 RSAPrivateKey data;
347 RSA *k = rsa;
348 size_t size;
349 int ret;
351 ret = decode_RSAPrivateKey(*pp, len, &data, &size);
352 if (ret)
353 return NULL;
355 *pp += size;
357 if (k == NULL) {
358 k = RSA_new();
359 if (k == NULL) {
360 free_RSAPrivateKey(&data);
361 return NULL;
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)
378 RSA_free(k);
379 return NULL;
382 return k;
386 i2d_RSAPrivateKey(RSA *rsa, unsigned char **pp)
388 RSAPrivateKey data;
389 size_t size;
390 int ret;
392 if (rsa->n == NULL || rsa->e == NULL || rsa->d == NULL || rsa->p == NULL ||
393 rsa->q == NULL || rsa->dmp1 == NULL || rsa->dmq1 == NULL ||
394 rsa->iqmp == NULL)
395 return -1;
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);
407 if (ret) {
408 free_RSAPrivateKey(&data);
409 return -1;
412 if (pp == NULL) {
413 size = length_RSAPrivateKey(&data);
414 free_RSAPrivateKey(&data);
415 } else {
416 void *p;
417 size_t len;
419 ASN1_MALLOC_ENCODE(RSAPrivateKey, p, len, &data, &size, ret);
420 free_RSAPrivateKey(&data);
421 if (ret)
422 return -1;
423 if (len != size)
424 abort();
426 memcpy(*pp, p, size);
427 free(p);
429 *pp += size;
432 return size;
436 i2d_RSAPublicKey(RSA *rsa, unsigned char **pp)
438 RSAPublicKey data;
439 size_t size;
440 int ret;
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);
448 return -1;
451 if (pp == NULL) {
452 size = length_RSAPublicKey(&data);
453 free_RSAPublicKey(&data);
454 } else {
455 void *p;
456 size_t len;
458 ASN1_MALLOC_ENCODE(RSAPublicKey, p, len, &data, &size, ret);
459 free_RSAPublicKey(&data);
460 if (ret)
461 return -1;
462 if (len != size)
463 abort();
465 memcpy(*pp, p, size);
466 free(p);
468 *pp += size;
471 return size;