12a988851Sagc /*-
22a988851Sagc  * Copyright (c) 2012 Alistair Crooks <agc@NetBSD.org>
32a988851Sagc  * All rights reserved.
42a988851Sagc  *
52a988851Sagc  * Redistribution and use in source and binary forms, with or without
62a988851Sagc  * modification, are permitted provided that the following conditions
72a988851Sagc  * are met:
82a988851Sagc  * 1. Redistributions of source code must retain the above copyright
92a988851Sagc  *    notice, this list of conditions and the following disclaimer.
102a988851Sagc  * 2. Redistributions in binary form must reproduce the above copyright
112a988851Sagc  *    notice, this list of conditions and the following disclaimer in the
122a988851Sagc  *    documentation and/or other materials provided with the distribution.
132a988851Sagc  *
142a988851Sagc  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
152a988851Sagc  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
162a988851Sagc  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
172a988851Sagc  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
182a988851Sagc  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
192a988851Sagc  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
202a988851Sagc  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
212a988851Sagc  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
222a988851Sagc  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
232a988851Sagc  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
242a988851Sagc  */
252a988851Sagc #include "config.h"
262a988851Sagc 
272a988851Sagc #include <sys/types.h>
282a988851Sagc 
292a988851Sagc #ifdef _KERNEL
302a988851Sagc # include <sys/kmem.h>
312a988851Sagc #else
322a988851Sagc # include <stdio.h>
332a988851Sagc # include <stdlib.h>
342a988851Sagc # include <string.h>
352a988851Sagc # include <unistd.h>
362a988851Sagc #endif
372a988851Sagc 
382a988851Sagc #include "misc.h"
392a988851Sagc #include "digest.h"
402a988851Sagc #include "rsa.h"
412a988851Sagc 
422a988851Sagc #ifndef USE_ARG
432a988851Sagc #define USE_ARG(x)	/*LINTED*/(void)&(x)
442a988851Sagc #endif
452a988851Sagc 
462a988851Sagc #define RSA_MAX_MODULUS_BITS	16384
472a988851Sagc #define RSA_SMALL_MODULUS_BITS	3072
482a988851Sagc #define RSA_MAX_PUBEXP_BITS	64 /* exponent limit enforced for "large" modulus only */
492a988851Sagc 
502a988851Sagc static int
rsa_padding_check_none(uint8_t * to,int tlen,const uint8_t * from,int flen,int num)512a988851Sagc rsa_padding_check_none(uint8_t *to, int tlen, const uint8_t *from, int flen, int num)
522a988851Sagc {
532a988851Sagc 	USE_ARG(num);
542a988851Sagc 	if (flen > tlen) {
552a988851Sagc 		printf("r too large\n");
562a988851Sagc 		return -1;
572a988851Sagc 	}
582a988851Sagc 	(void) memset(to, 0x0, tlen - flen);
592a988851Sagc 	(void) memcpy(to + tlen - flen, from, flen);
602a988851Sagc 	return tlen;
612a988851Sagc }
622a988851Sagc 
632a988851Sagc static int
lowlevel_rsa_private_encrypt(int plainc,const unsigned char * plain,unsigned char * encbuf,NETPGPV_RSA * rsa)649c15b0b0Sagc lowlevel_rsa_private_encrypt(int plainc, const unsigned char *plain, unsigned char *encbuf, NETPGPV_RSA *rsa)
652a988851Sagc {
664ee48979Sagc 	PGPV_BIGNUM	*decbn;
674ee48979Sagc 	PGPV_BIGNUM	*signedbn;
682a988851Sagc 	uint8_t	*decbuf;
692a988851Sagc 	int	 nbytes;
702a988851Sagc 	int	 signc;
712a988851Sagc 	int	 signedbytes;
722a988851Sagc 	int	 r;
732a988851Sagc 
742a988851Sagc 	decbuf = NULL;
752a988851Sagc 	r = -1;
764ee48979Sagc 	decbn = PGPV_BN_new();
774ee48979Sagc 	signedbn = PGPV_BN_new();
784ee48979Sagc 	nbytes = PGPV_BN_num_bytes(rsa->n);
792a988851Sagc 	decbuf = netpgp_allocate(1, nbytes);
802a988851Sagc 	/* add no padding */
812a988851Sagc 	memcpy(decbuf, plain, plainc);
824ee48979Sagc 	PGPV_BN_bin2bn(decbuf, nbytes, decbn);
834ee48979Sagc 	if (PGPV_BN_cmp(decbn, rsa->n) >= 0) {
842a988851Sagc 		printf("decbn too big\n");
852a988851Sagc 		goto err;
862a988851Sagc 	}
874ee48979Sagc 	if (!PGPV_BN_mod_exp(signedbn, decbn, rsa->d, rsa->n, NULL)) {
882a988851Sagc 		printf("bad mod_exp\n");
892a988851Sagc 		goto err;
902a988851Sagc 	}
914ee48979Sagc 	signedbytes = PGPV_BN_num_bytes(signedbn);
924ee48979Sagc 	signc = PGPV_BN_bn2bin(signedbn, &encbuf[nbytes - signedbytes]);
932a988851Sagc 	memset(encbuf, 0x0, nbytes - signc);
942a988851Sagc 	r = nbytes;
952a988851Sagc err:
962a988851Sagc 	netpgp_deallocate(decbuf, nbytes);
974ee48979Sagc 	PGPV_BN_clear_free(decbn);
984ee48979Sagc 	PGPV_BN_clear_free(signedbn);
992a988851Sagc 	return r;
1002a988851Sagc }
1012a988851Sagc 
1022a988851Sagc static int
lowlevel_rsa_public_encrypt(int plainc,const unsigned char * plain,unsigned char * encbuf,NETPGPV_RSA * rsa)1039c15b0b0Sagc lowlevel_rsa_public_encrypt(int plainc, const unsigned char *plain, unsigned char *encbuf, NETPGPV_RSA *rsa)
1042a988851Sagc {
1054ee48979Sagc 	PGPV_BIGNUM	*decbn;
1064ee48979Sagc 	PGPV_BIGNUM	*encbn;
1072a988851Sagc 	uint8_t	*decbuf;
1082a988851Sagc 	int	 nbytes;
1092a988851Sagc 	int	 encc;
1102a988851Sagc 	int	 r;
1112a988851Sagc 	int	 i;
1122a988851Sagc 
1132a988851Sagc 	r = -1;
1144ee48979Sagc 	decbn = PGPV_BN_new();
1154ee48979Sagc 	encbn = PGPV_BN_new();
1164ee48979Sagc 	nbytes = PGPV_BN_num_bytes(rsa->n);
1172a988851Sagc 	decbuf = netpgp_allocate(1, nbytes);
1182a988851Sagc 	(void) memcpy(decbuf, plain, plainc);
1194ee48979Sagc 	if (PGPV_BN_bin2bn(decbuf, nbytes, decbn) == NULL) {
1202a988851Sagc 		printf("bin2bn failed\n");
1212a988851Sagc 		goto err;
1222a988851Sagc 	}
1234ee48979Sagc 	if (PGPV_BN_cmp(decbn, rsa->n) >= 0) {
1244ee48979Sagc 		printf("PGPV_BN_cmp failed\n");
1252a988851Sagc 		goto err;
1262a988851Sagc 	}
1274ee48979Sagc 	if (!PGPV_BN_mod_exp(encbn, decbn, rsa->e, rsa->n, NULL)) {
1284ee48979Sagc 		printf("PGPV_BN_mod_exp failed\n");
1292a988851Sagc 		goto err;
1302a988851Sagc 	}
1314ee48979Sagc 	encc = PGPV_BN_num_bytes(encbn);
1324ee48979Sagc 	i = PGPV_BN_bn2bin(encbn, &encbuf[nbytes - encc]);
1332a988851Sagc 	(void) memset(encbuf, 0x0, nbytes - i);
1342a988851Sagc 	r = nbytes;
1352a988851Sagc err:
1362a988851Sagc 	if (decbuf) {
1372a988851Sagc 		memset(decbuf, 0x0, nbytes);
1382a988851Sagc 		netpgp_deallocate(decbuf, nbytes);
1392a988851Sagc 	}
1404ee48979Sagc 	PGPV_BN_clear_free(decbn);
1414ee48979Sagc 	PGPV_BN_clear_free(encbn);
1422a988851Sagc 	return r;
1432a988851Sagc }
1442a988851Sagc 
1452a988851Sagc static int
lowlevel_rsa_private_decrypt(int enclen,const unsigned char * encbuf,unsigned char * to,NETPGPV_RSA * rsa)1469c15b0b0Sagc lowlevel_rsa_private_decrypt(int enclen, const unsigned char *encbuf, unsigned char *to, NETPGPV_RSA *rsa)
1472a988851Sagc {
1484ee48979Sagc 	PGPV_BIGNUM	*encbn;
1494ee48979Sagc 	PGPV_BIGNUM	*decbn;
1502a988851Sagc 	uint8_t	*buf;
1512a988851Sagc 	int	 nbytes;
1522a988851Sagc 	int	 j;
1532a988851Sagc 	int	 r;
1542a988851Sagc 
1552a988851Sagc 	r = -1;
1562a988851Sagc 	decbn = encbn = NULL;
1572a988851Sagc 	buf = NULL;
1584ee48979Sagc 	if (PGPV_BN_num_bits(rsa->n) > RSA_MAX_MODULUS_BITS) {
1592a988851Sagc 		return -1;
1602a988851Sagc 	}
1614ee48979Sagc 	if (PGPV_BN_cmp(rsa->n, rsa->e) <= 0) {
1622a988851Sagc 		return -1;
1632a988851Sagc 	}
1644ee48979Sagc 	encbn = PGPV_BN_new();
1654ee48979Sagc 	decbn = PGPV_BN_new();
1664ee48979Sagc 	nbytes = PGPV_BN_num_bytes(rsa->n);
1672a988851Sagc 	buf = netpgp_allocate(1, nbytes);
1682a988851Sagc 	if (enclen > nbytes) {
1692a988851Sagc 		printf("bad enclen\n");
1702a988851Sagc 		goto err;
1712a988851Sagc 	}
1724ee48979Sagc 	PGPV_BN_bin2bn(encbuf, enclen, encbn);
1734ee48979Sagc 	if (PGPV_BN_cmp(encbn, rsa->n) >= 0) {
1742a988851Sagc 		printf("bad encbn\n");
1752a988851Sagc 		goto err;
1762a988851Sagc 	}
1774ee48979Sagc 	PGPV_BN_mod_exp(decbn, encbn, rsa->d, rsa->n, NULL);
1784ee48979Sagc 	j = PGPV_BN_bn2bin(decbn, buf);
1792a988851Sagc 	r = rsa_padding_check_none(to, nbytes, buf, j, nbytes);
1802a988851Sagc err:
1814ee48979Sagc 	PGPV_BN_clear_free(encbn);
1824ee48979Sagc 	PGPV_BN_clear_free(decbn);
1832a988851Sagc 	netpgp_deallocate(buf, nbytes);
1842a988851Sagc 	return r;
1852a988851Sagc }
1862a988851Sagc 
1872a988851Sagc static int
lowlevel_rsa_public_decrypt(const uint8_t * encbuf,int enclen,uint8_t * dec,const netpgpv_rsa_pubkey_t * rsa)1889c15b0b0Sagc lowlevel_rsa_public_decrypt(const uint8_t *encbuf, int enclen, uint8_t *dec, const netpgpv_rsa_pubkey_t *rsa)
1892a988851Sagc {
1902a988851Sagc 	uint8_t		*decbuf;
1914ee48979Sagc 	PGPV_BIGNUM		*decbn;
1924ee48979Sagc 	PGPV_BIGNUM		*encbn;
1932a988851Sagc 	int		 decbytes;
1942a988851Sagc 	int		 nbytes;
1952a988851Sagc 	int		 r;
1962a988851Sagc 
1972a988851Sagc 	nbytes = 0;
1982a988851Sagc 	r = -1;
1992a988851Sagc 	decbuf = NULL;
2002a988851Sagc 	decbn = encbn = NULL;
2014ee48979Sagc 	if (PGPV_BN_num_bits(rsa->n) > RSA_MAX_MODULUS_BITS) {
2022a988851Sagc 		printf("rsa r modulus too large\n");
2032a988851Sagc 		goto err;
2042a988851Sagc 	}
2054ee48979Sagc 	if (PGPV_BN_cmp(rsa->n, rsa->e) <= 0) {
2062a988851Sagc 		printf("rsa r bad n value\n");
2072a988851Sagc 		goto err;
2082a988851Sagc 	}
2094ee48979Sagc 	if (PGPV_BN_num_bits(rsa->n) > RSA_SMALL_MODULUS_BITS &&
2104ee48979Sagc 	    PGPV_BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS) {
2112a988851Sagc 		printf("rsa r bad exponent limit\n");
2122a988851Sagc 		goto err;
2132a988851Sagc 	}
2144ee48979Sagc 	if ((encbn = PGPV_BN_new()) == NULL ||
2154ee48979Sagc 	    (decbn = PGPV_BN_new()) == NULL ||
2164ee48979Sagc 	    (decbuf = netpgp_allocate(1, nbytes = PGPV_BN_num_bytes(rsa->n))) == NULL) {
2172a988851Sagc 		printf("allocation failure\n");
2182a988851Sagc 		goto err;
2192a988851Sagc 	}
2202a988851Sagc 	if (enclen > nbytes) {
2212a988851Sagc 		printf("rsa r > mod len\n");
2222a988851Sagc 		goto err;
2232a988851Sagc 	}
2244ee48979Sagc 	if (PGPV_BN_bin2bn(encbuf, enclen, encbn) == NULL) {
2252a988851Sagc 		printf("null encrypted BN\n");
2262a988851Sagc 		goto err;
2272a988851Sagc 	}
2284ee48979Sagc 	if (PGPV_BN_cmp(encbn, rsa->n) >= 0) {
2292a988851Sagc 		printf("rsa r data too large for modulus\n");
2302a988851Sagc 		goto err;
2312a988851Sagc 	}
2324ee48979Sagc 	if (PGPV_BN_mod_exp(decbn, encbn, rsa->e, rsa->n, NULL) < 0) {
2334ee48979Sagc 		printf("PGPV_BN_mod_exp < 0\n");
2342a988851Sagc 		goto err;
2352a988851Sagc 	}
2364ee48979Sagc 	decbytes = PGPV_BN_num_bytes(decbn);
2374ee48979Sagc 	(void) PGPV_BN_bn2bin(decbn, decbuf);
2382a988851Sagc 	if ((r = rsa_padding_check_none(dec, nbytes, decbuf, decbytes, 0)) < 0) {
2392a988851Sagc 		printf("rsa r padding check failed\n");
2402a988851Sagc 	}
2412a988851Sagc err:
2424ee48979Sagc 	PGPV_BN_free(encbn);
2434ee48979Sagc 	PGPV_BN_free(decbn);
2442a988851Sagc 	if (decbuf != NULL) {
2452a988851Sagc 		(void) memset(decbuf, 0x0, nbytes);
2462a988851Sagc 		netpgp_deallocate(decbuf, nbytes);
2472a988851Sagc 	}
2482a988851Sagc 	return r;
2492a988851Sagc }
2502a988851Sagc 
2512a988851Sagc #if 0
2522a988851Sagc /**
2532a988851Sagc   @file rsa_make_key.c
2542a988851Sagc   RSA key generation, Tom St Denis
2552a988851Sagc */
2562a988851Sagc 
2572a988851Sagc /**
2582a988851Sagc    Create an RSA key
2592a988851Sagc    @param prng     An active PRNG state
2602a988851Sagc    @param wprng    The index of the PRNG desired
2612a988851Sagc    @param size     The size of the modulus (key size) desired (octets)
2622a988851Sagc    @param e        The "e" value (public key).  e==65537 is a good choice
2632a988851Sagc    @param key      [out] Destination of a newly created private key pair
2642a988851Sagc    @return CRYPT_OK if successful, upon error all allocated ram is freed
2652a988851Sagc */
2662a988851Sagc static int
2672a988851Sagc rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
2682a988851Sagc {
2692a988851Sagc 	void *p, *q, *tmp1, *tmp2, *tmp3;
2702a988851Sagc 	int    err;
2712a988851Sagc 
2722a988851Sagc 	LTC_ARGCHK(ltc_mp.name != NULL);
2732a988851Sagc 	LTC_ARGCHK(key         != NULL);
2742a988851Sagc 
2752a988851Sagc 	if ((size < (MIN_RSA_SIZE/8)) || (size > (MAX_RSA_SIZE/8))) {
2762a988851Sagc 		return CRYPT_INVALID_KEYSIZE;
2772a988851Sagc 	}
2782a988851Sagc 
2792a988851Sagc 	if ((e < 3) || ((e & 1) == 0)) {
2802a988851Sagc 		return CRYPT_INVALID_ARG;
2812a988851Sagc 	}
2822a988851Sagc 
2832a988851Sagc 	if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
2842a988851Sagc 		return err;
2852a988851Sagc 	}
2862a988851Sagc 
2872a988851Sagc 	if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != CRYPT_OK) {
2882a988851Sagc 		return err;
2892a988851Sagc 	}
2902a988851Sagc 
2912a988851Sagc 	/* make primes p and q (optimization provided by Wayne Scott) */
2922a988851Sagc 		/* tmp3 = e */
2932a988851Sagc 	if ((err = mp_set_int(tmp3, e)) != CRYPT_OK) {
2942a988851Sagc 		goto errkey;
2952a988851Sagc 	}
2962a988851Sagc 
2972a988851Sagc 	/* make prime "p" */
2982a988851Sagc 	do {
2992a988851Sagc 		if ((err = rand_prime( p, size/2, prng, wprng)) != CRYPT_OK) {
3002a988851Sagc 			goto errkey;
3012a988851Sagc 		}
3022a988851Sagc 		/* tmp1 = p-1 */
3032a988851Sagc 		if ((err = mp_sub_d( p, 1,  tmp1)) != CRYPT_OK) {
3042a988851Sagc 			goto errkey;
3052a988851Sagc 		}
3062a988851Sagc 		/* tmp2 = gcd(p-1, e) */
3072a988851Sagc 		if ((err = mp_gcd( tmp1,  tmp3,  tmp2)) != CRYPT_OK) {
3082a988851Sagc 			goto errkey;
3092a988851Sagc 		}
3102a988851Sagc 	} while (mp_cmp_d( tmp2, 1) != 0);
3112a988851Sagc 	/* while e divides p-1 */
3122a988851Sagc 
3132a988851Sagc 	/* make prime "q" */
3142a988851Sagc 	do {
3152a988851Sagc 		if ((err = rand_prime( q, size/2, prng, wprng)) != CRYPT_OK) {
3162a988851Sagc 			goto errkey;
3172a988851Sagc 		}
3182a988851Sagc 		/* tmp1 = q-1 */
3192a988851Sagc 		if ((err = mp_sub_d( q, 1,  tmp1)) != CRYPT_OK) {
3202a988851Sagc 			goto errkey;
3212a988851Sagc 		}
3222a988851Sagc 		/* tmp2 = gcd(q-1, e) */
3232a988851Sagc 		if ((err = mp_gcd( tmp1,  tmp3,  tmp2)) != CRYPT_OK) {
3242a988851Sagc 			goto errkey;
3252a988851Sagc 		}
3262a988851Sagc 	} while (mp_cmp_d( tmp2, 1) != 0);
3272a988851Sagc 	/* while e divides q-1 */
3282a988851Sagc 
3292a988851Sagc 	/* tmp1 = lcm(p-1, q-1) */
3302a988851Sagc 		/* tmp2 = p-1 */
3312a988851Sagc 	if ((err = mp_sub_d( p, 1,  tmp2)) != CRYPT_OK) {
3322a988851Sagc 		goto errkey;
3332a988851Sagc 	}
3342a988851Sagc 	/* tmp1 = q-1 (previous do/while loop) */
3352a988851Sagc 		/* tmp1 = lcm(p-1, q-1) */
3362a988851Sagc 	if ((err = mp_lcm( tmp1,  tmp2,  tmp1)) != CRYPT_OK) {
3372a988851Sagc 		goto errkey;
3382a988851Sagc 	}
3392a988851Sagc 
3402a988851Sagc 	/* make key */
3412a988851Sagc 	if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {
3422a988851Sagc 		goto errkey;
3432a988851Sagc 	}
3442a988851Sagc 
3452a988851Sagc 	/* key->e =  e */
3462a988851Sagc 	if ((err = mp_set_int( key->e, e)) != CRYPT_OK) {
3472a988851Sagc 		goto errkey;
3482a988851Sagc 	}
3492a988851Sagc 	/* key->d = 1/e mod lcm(p-1,q-1) */
3502a988851Sagc 	if ((err = mp_invmod( key->e,  tmp1,  key->d)) != CRYPT_OK) {
3512a988851Sagc 		goto errkey;
3522a988851Sagc 	}
3532a988851Sagc 	/* key->N = pq */
3542a988851Sagc 	if ((err = mp_mul( p,  q,  key->N)) != CRYPT_OK) {
3552a988851Sagc 		goto errkey;
3562a988851Sagc 	}
3572a988851Sagc 
3582a988851Sagc 	/* optimize for CRT now */
3592a988851Sagc 	/* find d mod q-1 and d mod p-1 */
3602a988851Sagc 	/* tmp1 = q-1 */
3612a988851Sagc 	if ((err = mp_sub_d( p, 1,  tmp1)) != CRYPT_OK) {
3622a988851Sagc 		goto errkey;
3632a988851Sagc 	}
3642a988851Sagc 	/* tmp2 = p-1 */
3652a988851Sagc 	if ((err = mp_sub_d( q, 1,  tmp2)) != CRYPT_OK) {
3662a988851Sagc 		goto errkey;
3672a988851Sagc 	}
3682a988851Sagc 	/* dP = d mod p-1 */
3692a988851Sagc 	if ((err = mp_mod( key->d,  tmp1,  key->dP)) != CRYPT_OK) {
3702a988851Sagc 		goto errkey;
3712a988851Sagc 	}
3722a988851Sagc 	/* dQ = d mod q-1 */
3732a988851Sagc 	if ((err = mp_mod( key->d,  tmp2,  key->dQ)) != CRYPT_OK) {
3742a988851Sagc 		goto errkey;
3752a988851Sagc 	}
3762a988851Sagc 	/* qP = 1/q mod p */
3772a988851Sagc 	if ((err = mp_invmod( q,  p,  key->qP)) != CRYPT_OK) {
3782a988851Sagc 		got oerrkey;
3792a988851Sagc 	}
3802a988851Sagc 
3812a988851Sagc 	if ((err = mp_copy( p,  key->p)) != CRYPT_OK) {
3822a988851Sagc 		goto errkey;
3832a988851Sagc 		}
3842a988851Sagc 	if ((err = mp_copy( q,  key->q)) != CRYPT_OK) {
3852a988851Sagc 		goto errkey;
3862a988851Sagc 	}
3872a988851Sagc 
3882a988851Sagc 	/* set key type (in this case it's CRT optimized) */
3892a988851Sagc 	key->type = PK_PRIVATE;
3902a988851Sagc 
3912a988851Sagc 	/* return ok and free temps */
3922a988851Sagc 	err = CRYPT_OK;
3932a988851Sagc 	goto cleanup;
3942a988851Sagc errkey:
3952a988851Sagc 	mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
3962a988851Sagc cleanup:
3972a988851Sagc 	mp_clear_multi(tmp3, tmp2, tmp1, p, q, NULL);
3982a988851Sagc 	return err;
3992a988851Sagc }
4002a988851Sagc #endif
4012a988851Sagc 
4022a988851Sagc #define HASHBUF_LEN	512
4032a988851Sagc 
4042a988851Sagc #define DSA_MAX_MODULUS_BITS	10000
4052a988851Sagc 
4062a988851Sagc static int
dsa_do_verify(const unsigned char * calculated,int dgst_len,const netpgpv_dsasig_t * sig,netpgpv_mpi_dsa_t * dsa)4079c15b0b0Sagc dsa_do_verify(const unsigned char *calculated, int dgst_len, const netpgpv_dsasig_t *sig, netpgpv_mpi_dsa_t *dsa)
4082a988851Sagc {
4094ee48979Sagc 	PGPV_BIGNUM		 *M;
4104ee48979Sagc 	PGPV_BIGNUM		 *W;
4114ee48979Sagc 	PGPV_BIGNUM		 *t1;
4122a988851Sagc 	int		 ret = -1;
4132a988851Sagc 	int		 qbits;
4142a988851Sagc 
4152a988851Sagc 	if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
4162a988851Sagc 		return 0;
4172a988851Sagc 	}
4182a988851Sagc 	M = W = t1 = NULL;
4194ee48979Sagc 	qbits = PGPV_BN_num_bits(dsa->q);
4202a988851Sagc 	switch(qbits) {
4212a988851Sagc 	case 160:
4222a988851Sagc 	case 224:
4232a988851Sagc 	case 256:
4242a988851Sagc 		/* openssl sources say these are the valid values */
4252a988851Sagc 		/* according to FIPS 186-3 */
4262a988851Sagc 		break;
4272a988851Sagc 	default:
4282a988851Sagc 		printf("dsa: bad # of Q bits\n");
4292a988851Sagc 		return 0;
4302a988851Sagc 	}
4314ee48979Sagc 	if (PGPV_BN_num_bits(dsa->p) > DSA_MAX_MODULUS_BITS) {
4322a988851Sagc 		printf("dsa: p too large\n");
4332a988851Sagc 		return 0;
4342a988851Sagc 	}
4352a988851Sagc 	/* no love for SHA512? */
4362a988851Sagc 	if (dgst_len > SHA256_DIGEST_LENGTH) {
4372a988851Sagc 		printf("dsa: digest too long\n");
4382a988851Sagc 		return 0;
4392a988851Sagc 	}
4402a988851Sagc 	ret = 0;
4414ee48979Sagc 	if ((M = PGPV_BN_new()) == NULL ||
4424ee48979Sagc 	    (W = PGPV_BN_new()) == NULL ||
4434ee48979Sagc 	    (t1 = PGPV_BN_new()) == NULL) {
4442a988851Sagc 		goto err;
4452a988851Sagc 	}
4464ee48979Sagc 	if (PGPV_BN_is_zero(sig->r) ||
4474ee48979Sagc 	    PGPV_BN_is_negative(sig->r) ||
4484ee48979Sagc 	    PGPV_BN_cmp(sig->r, dsa->q) >= 0) {
4492a988851Sagc 		goto err;
4502a988851Sagc 	}
4514ee48979Sagc 	if (PGPV_BN_is_zero(sig->s) ||
4524ee48979Sagc 	    PGPV_BN_is_negative(sig->s) ||
4534ee48979Sagc 	    PGPV_BN_cmp(sig->s, dsa->q) >= 0) {
4542a988851Sagc 		goto err;
4552a988851Sagc 	}
4564ee48979Sagc 	if (PGPV_BN_mod_inverse(W, sig->s, dsa->q, NULL) != MP_OKAY) {
4572a988851Sagc 		goto err;
4582a988851Sagc 	}
4592a988851Sagc 	if (dgst_len > qbits / 8) {
4602a988851Sagc 		dgst_len = qbits / 8;
4612a988851Sagc 	}
4624ee48979Sagc 	if (PGPV_BN_bin2bn(calculated, dgst_len, M) == NULL) {
4632a988851Sagc 		goto err;
4642a988851Sagc 	}
4654ee48979Sagc 	if (!PGPV_BN_mod_mul(M, M, W, dsa->q, NULL)) {
4662a988851Sagc 		goto err;
4672a988851Sagc 	}
4684ee48979Sagc 	if (!PGPV_BN_mod_mul(W, sig->r, W, dsa->q, NULL)) {
4692a988851Sagc 		goto err;
4702a988851Sagc 	}
4714ee48979Sagc 	if (!PGPV_BN_mod_exp(dsa->p, t1, dsa->g, M, NULL)) {
4722a988851Sagc 		goto err;
4732a988851Sagc 	}
4744ee48979Sagc 	if (!PGPV_BN_div(NULL, M, t1, dsa->q, NULL)) {
4752a988851Sagc 		goto err;
4762a988851Sagc 	}
4774ee48979Sagc 	ret = (PGPV_BN_cmp(M, sig->r) == 0);
4782a988851Sagc err:
4792a988851Sagc 	if (M) {
4804ee48979Sagc 		PGPV_BN_free(M);
4812a988851Sagc 	}
4822a988851Sagc 	if (W) {
4834ee48979Sagc 		PGPV_BN_free(W);
4842a988851Sagc 	}
4852a988851Sagc 	if (t1) {
4864ee48979Sagc 		PGPV_BN_free(t1);
4872a988851Sagc 	}
4882a988851Sagc 	return ret;
4892a988851Sagc }
4902a988851Sagc 
4912a988851Sagc /*************************************************************************/
4922a988851Sagc 
4932a988851Sagc int
netpgpv_RSA_size(const NETPGPV_RSA * rsa)4949c15b0b0Sagc netpgpv_RSA_size(const NETPGPV_RSA *rsa)
4952a988851Sagc {
4964ee48979Sagc 	return (rsa == NULL) ? 0 : PGPV_BN_num_bits(rsa->n);
4972a988851Sagc }
4982a988851Sagc 
4992a988851Sagc int
netpgpv_DSA_size(const NETPGPV_DSA * dsa)5009c15b0b0Sagc netpgpv_DSA_size(const NETPGPV_DSA *dsa)
5012a988851Sagc {
5024ee48979Sagc 	return (dsa == NULL) ? 0 : PGPV_BN_num_bits(dsa->p);
5032a988851Sagc }
5042a988851Sagc 
5052a988851Sagc unsigned
netpgpv_dsa_verify(const signature_t * signature,const netpgpv_dsa_pubkey_t * pubdsa,const uint8_t * calculated,size_t hash_length)5069c15b0b0Sagc netpgpv_dsa_verify(const signature_t *signature,
5079c15b0b0Sagc 	const netpgpv_dsa_pubkey_t *pubdsa, const uint8_t *calculated,
5089c15b0b0Sagc 	size_t hash_length)
5092a988851Sagc {
5109c15b0b0Sagc 	netpgpv_mpi_dsa_t	odsa;
5119c15b0b0Sagc 	netpgpv_dsasig_t	osig;
5122a988851Sagc 	unsigned		qlen;
5132a988851Sagc 	int	             ret;
5142a988851Sagc 
5152a988851Sagc 	if (signature == NULL || pubdsa == NULL || calculated == NULL) {
516*95593e56Srillig 		return (unsigned)-1;
5172a988851Sagc 	}
5182a988851Sagc 	(void) memset(&osig, 0x0, sizeof(osig));
5192a988851Sagc 	(void) memset(&odsa, 0x0, sizeof(odsa));
5204ee48979Sagc 	PGPV_BN_copy(osig.r, signature->dsa.r);
5214ee48979Sagc 	PGPV_BN_copy(osig.s, signature->dsa.s);
5222a988851Sagc 	odsa.p = pubdsa->p;
5232a988851Sagc 	odsa.q = pubdsa->q;
5242a988851Sagc 	odsa.g = pubdsa->g;
5252a988851Sagc 	odsa.pub_key = pubdsa->y;
5264ee48979Sagc 	if ((qlen = PGPV_BN_num_bytes(odsa.q)) < hash_length) {
5272a988851Sagc 		hash_length = qlen;
5282a988851Sagc 	}
5292a988851Sagc 	ret = dsa_do_verify(calculated, (int)hash_length, &signature->dsa, &odsa);
5302a988851Sagc 	if (ret < 0) {
5312a988851Sagc 		return 0;
5322a988851Sagc 	}
5334ee48979Sagc 	PGPV_BN_free(odsa.p);
5344ee48979Sagc 	PGPV_BN_free(odsa.q);
5354ee48979Sagc 	PGPV_BN_free(odsa.g);
5364ee48979Sagc 	PGPV_BN_free(odsa.pub_key);
5372a988851Sagc 	odsa.p = odsa.q = odsa.g = odsa.pub_key = NULL;
5384ee48979Sagc 	PGPV_BN_free(osig.r);
5394ee48979Sagc 	PGPV_BN_free(osig.s);
5402a988851Sagc 	osig.r = osig.s = NULL;
5412a988851Sagc 	return (unsigned)ret;
5422a988851Sagc }
5432a988851Sagc 
5449c15b0b0Sagc NETPGPV_RSA *
netpgpv_RSA_new(void)5459c15b0b0Sagc netpgpv_RSA_new(void)
5462a988851Sagc {
5479c15b0b0Sagc 	return netpgp_allocate(1, sizeof(NETPGPV_RSA));
5482a988851Sagc }
5492a988851Sagc 
5502a988851Sagc void
netpgpv_RSA_free(NETPGPV_RSA * rsa)5519c15b0b0Sagc netpgpv_RSA_free(NETPGPV_RSA *rsa)
5522a988851Sagc {
5532a988851Sagc 	if (rsa) {
5542a988851Sagc 		netpgp_deallocate(rsa, sizeof(*rsa));
5552a988851Sagc 	}
5562a988851Sagc }
5572a988851Sagc 
5582a988851Sagc int
netpgpv_RSA_check_key(NETPGPV_RSA * rsa)5599c15b0b0Sagc netpgpv_RSA_check_key(NETPGPV_RSA *rsa)
5602a988851Sagc {
5614ee48979Sagc 	PGPV_BIGNUM	*calcn;
5622a988851Sagc 	int	 ret;
5632a988851Sagc 
5642a988851Sagc 	ret = 0;
5652a988851Sagc 	if (rsa == NULL || rsa->p == NULL || rsa->q == NULL || rsa->n == NULL) {
5662a988851Sagc 		return -1;
5672a988851Sagc 	}
5682a988851Sagc 	/* check that p and q are coprime, and that n = p*q. */
5694ee48979Sagc 	if (!PGPV_BN_is_prime(rsa->p, 1, NULL, NULL, NULL) ||
5704ee48979Sagc 	    !PGPV_BN_is_prime(rsa->q, 1, NULL, NULL, NULL)) {
5712a988851Sagc 		return 0;
5722a988851Sagc 	}
5734ee48979Sagc 	calcn = PGPV_BN_new();
5744ee48979Sagc         PGPV_BN_mul(calcn, rsa->p, rsa->q, NULL);
5754ee48979Sagc 	if (PGPV_BN_cmp(calcn, rsa->n) != 0) {
5762a988851Sagc 		goto errout;
5772a988851Sagc 	}
5782a988851Sagc 	/* XXX - check that d*e = 1 mod (p-1*q-1) */
5792a988851Sagc 	ret = 1;
5802a988851Sagc errout:
5814ee48979Sagc 	PGPV_BN_clear_free(calcn);
5822a988851Sagc 	return ret;
5832a988851Sagc }
5842a988851Sagc 
5859c15b0b0Sagc NETPGPV_RSA *
netpgpv_RSA_generate_key(int num,unsigned long e,void (* callback)(int,int,void *),void * cb_arg)5869c15b0b0Sagc netpgpv_RSA_generate_key(int num, unsigned long e, void (*callback)(int,int,void *), void *cb_arg)
5872a988851Sagc {
5882a988851Sagc 	/* STUBBED */
5892a988851Sagc 	USE_ARG(num);
5902a988851Sagc 	USE_ARG(e);
5912a988851Sagc 	USE_ARG(callback);
5922a988851Sagc 	USE_ARG(cb_arg);
5932a988851Sagc 	printf("RSA_generate_key stubbed\n");
5949c15b0b0Sagc 	return netpgpv_RSA_new();
5952a988851Sagc }
5962a988851Sagc 
5972a988851Sagc /* encrypt */
5982a988851Sagc int
netpgpv_RSA_public_encrypt(int plainc,const unsigned char * plain,unsigned char * encbuf,NETPGPV_RSA * rsa,int padding)5999c15b0b0Sagc netpgpv_RSA_public_encrypt(int plainc, const unsigned char *plain, unsigned char *encbuf, NETPGPV_RSA *rsa, int padding)
6002a988851Sagc {
6012a988851Sagc 	USE_ARG(padding);
6022a988851Sagc 	if (plain == NULL || encbuf == NULL || rsa == NULL) {
6032a988851Sagc 		return -1;
6042a988851Sagc 	}
6052a988851Sagc 	return lowlevel_rsa_public_encrypt(plainc, plain, encbuf, rsa);
6062a988851Sagc }
6072a988851Sagc 
6082a988851Sagc /* decrypt */
6092a988851Sagc int
netpgpv_RSA_private_decrypt(int flen,const unsigned char * from,unsigned char * to,NETPGPV_RSA * rsa,int padding)6109c15b0b0Sagc netpgpv_RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to, NETPGPV_RSA *rsa, int padding)
6112a988851Sagc {
6122a988851Sagc 	USE_ARG(padding);
6132a988851Sagc 	if (from == NULL || to == NULL || rsa == NULL) {
6142a988851Sagc 		return -1;
6152a988851Sagc 	}
6162a988851Sagc 	return lowlevel_rsa_private_decrypt(flen, from, to, rsa);
6172a988851Sagc }
6182a988851Sagc 
6192a988851Sagc /* sign */
6202a988851Sagc int
netpgpv_RSA_private_encrypt(int plainc,const unsigned char * plain,unsigned char * encbuf,NETPGPV_RSA * rsa,int padding)6219c15b0b0Sagc netpgpv_RSA_private_encrypt(int plainc, const unsigned char *plain, unsigned char *encbuf, NETPGPV_RSA *rsa, int padding)
6222a988851Sagc {
6232a988851Sagc 	USE_ARG(padding);
6242a988851Sagc 	if (plain == NULL || encbuf == NULL || rsa == NULL) {
6252a988851Sagc 		return -1;
6262a988851Sagc 	}
6272a988851Sagc 	return lowlevel_rsa_private_encrypt(plainc, plain, encbuf, rsa);
6282a988851Sagc }
6292a988851Sagc 
6302a988851Sagc /* verify */
6312a988851Sagc int
netpgpv_RSA_public_decrypt(int enclen,const unsigned char * enc,unsigned char * dec,NETPGPV_RSA * rsa,int padding)6329c15b0b0Sagc netpgpv_RSA_public_decrypt(int enclen, const unsigned char *enc, unsigned char *dec, NETPGPV_RSA *rsa, int padding)
6332a988851Sagc {
6349c15b0b0Sagc 	netpgpv_rsa_pubkey_t	pub;
6352a988851Sagc 	int			ret;
6362a988851Sagc 
6372a988851Sagc 	if (enc == NULL || dec == NULL || rsa == NULL) {
6382a988851Sagc 		return 0;
6392a988851Sagc 	}
6402a988851Sagc 	USE_ARG(padding);
6412a988851Sagc 	(void) memset(&pub, 0x0, sizeof(pub));
6424ee48979Sagc 	pub.n = PGPV_BN_dup(rsa->n);
6434ee48979Sagc 	pub.e = PGPV_BN_dup(rsa->e);
6442a988851Sagc 	ret = lowlevel_rsa_public_decrypt(enc, enclen, dec, &pub);
6454ee48979Sagc 	PGPV_BN_free(pub.n);
6464ee48979Sagc 	PGPV_BN_free(pub.e);
6472a988851Sagc 	return ret;
6482a988851Sagc }
6492a988851Sagc 
6502a988851Sagc /***********************************************************************/
6512a988851Sagc 
6529c15b0b0Sagc NETPGPV_DSA *
netpgpv_DSA_new(void)6539c15b0b0Sagc netpgpv_DSA_new(void)
6542a988851Sagc {
6559c15b0b0Sagc 	return netpgp_allocate(1, sizeof(NETPGPV_DSA));
6562a988851Sagc }
6572a988851Sagc 
6582a988851Sagc void
netpgpv_DSA_free(NETPGPV_DSA * dsa)6599c15b0b0Sagc netpgpv_DSA_free(NETPGPV_DSA *dsa)
6602a988851Sagc {
6612a988851Sagc 	if (dsa) {
6622a988851Sagc 		netpgp_deallocate(dsa, sizeof(*dsa));
6632a988851Sagc 	}
6642a988851Sagc }
6652a988851Sagc 
6669c15b0b0Sagc NETPGPV_DSA_SIG *
netpgpv_DSA_SIG_new(void)6679c15b0b0Sagc netpgpv_DSA_SIG_new(void)
6682a988851Sagc {
6699c15b0b0Sagc 	return netpgp_allocate(1, sizeof(NETPGPV_DSA_SIG));
6702a988851Sagc }
6712a988851Sagc 
6722a988851Sagc void
netpgpv_DSA_SIG_free(NETPGPV_DSA_SIG * sig)6739c15b0b0Sagc netpgpv_DSA_SIG_free(NETPGPV_DSA_SIG *sig)
6742a988851Sagc {
6752a988851Sagc 	if (sig) {
6762a988851Sagc 		netpgp_deallocate(sig, sizeof(*sig));
6772a988851Sagc 	}
6782a988851Sagc }
6792a988851Sagc 
6809c15b0b0Sagc NETPGPV_DSA_SIG *
netpgpv_DSA_do_sign(const unsigned char * dgst,int dlen,NETPGPV_DSA * dsa)6819c15b0b0Sagc netpgpv_DSA_do_sign(const unsigned char *dgst, int dlen, NETPGPV_DSA *dsa)
6822a988851Sagc {
6832a988851Sagc 	/* STUBBED */
6842a988851Sagc 	USE_ARG(dgst);
6852a988851Sagc 	USE_ARG(dlen);
6862a988851Sagc 	USE_ARG(dsa);
6872a988851Sagc 	printf("DSA_do_sign stubbed\n");
6889c15b0b0Sagc 	return netpgpv_DSA_SIG_new();
6892a988851Sagc }
6902a988851Sagc 
6912a988851Sagc int
netpgpv_DSA_do_verify(const unsigned char * dgst,int dgst_len,NETPGPV_DSA_SIG * sig,NETPGPV_DSA * dsa)6929c15b0b0Sagc netpgpv_DSA_do_verify(const unsigned char *dgst, int dgst_len, NETPGPV_DSA_SIG *sig, NETPGPV_DSA *dsa)
6932a988851Sagc {
6942a988851Sagc 	if (dgst == NULL || dgst_len == 0 || sig == NULL || dsa == NULL) {
6952a988851Sagc 		return -1;
6962a988851Sagc 	}
6972a988851Sagc 	return dsa_do_verify(dgst, dgst_len, sig, dsa);
6982a988851Sagc }
699