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