125f78d91Sagc /*-
225f78d91Sagc * Copyright (c) 2012 Alistair Crooks <agc@NetBSD.org>
325f78d91Sagc * All rights reserved.
425f78d91Sagc *
525f78d91Sagc * Redistribution and use in source and binary forms, with or without
625f78d91Sagc * modification, are permitted provided that the following conditions
725f78d91Sagc * are met:
825f78d91Sagc * 1. Redistributions of source code must retain the above copyright
925f78d91Sagc * notice, this list of conditions and the following disclaimer.
1025f78d91Sagc * 2. Redistributions in binary form must reproduce the above copyright
1125f78d91Sagc * notice, this list of conditions and the following disclaimer in the
1225f78d91Sagc * documentation and/or other materials provided with the distribution.
1325f78d91Sagc *
1425f78d91Sagc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1525f78d91Sagc * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1625f78d91Sagc * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1725f78d91Sagc * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1825f78d91Sagc * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1925f78d91Sagc * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2025f78d91Sagc * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2125f78d91Sagc * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2225f78d91Sagc * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2325f78d91Sagc * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2425f78d91Sagc */
2525f78d91Sagc #include "config.h"
2625f78d91Sagc
2725f78d91Sagc #include <sys/types.h>
2825f78d91Sagc
2925f78d91Sagc #ifdef _KERNEL
3025f78d91Sagc # include <sys/kmem.h>
3125f78d91Sagc #else
3225f78d91Sagc # include <stdio.h>
3325f78d91Sagc # include <stdlib.h>
3425f78d91Sagc # include <string.h>
3525f78d91Sagc # include <unistd.h>
3625f78d91Sagc #endif
3725f78d91Sagc
3825f78d91Sagc #include "misc.h"
3925f78d91Sagc #include "digest.h"
4025f78d91Sagc #include "rsa.h"
4125f78d91Sagc
4225f78d91Sagc #ifndef USE_ARG
4325f78d91Sagc #define USE_ARG(x) /*LINTED*/(void)&(x)
4425f78d91Sagc #endif
4525f78d91Sagc
4625f78d91Sagc #define RSA_MAX_MODULUS_BITS 16384
4725f78d91Sagc #define RSA_SMALL_MODULUS_BITS 3072
4825f78d91Sagc #define RSA_MAX_PUBEXP_BITS 64 /* exponent limit enforced for "large" modulus only */
4925f78d91Sagc
5025f78d91Sagc static int
rsa_padding_check_none(uint8_t * to,int tlen,const uint8_t * from,int flen,int num)5125f78d91Sagc rsa_padding_check_none(uint8_t *to, int tlen, const uint8_t *from, int flen, int num)
5225f78d91Sagc {
5325f78d91Sagc USE_ARG(num);
5425f78d91Sagc if (flen > tlen) {
5525f78d91Sagc printf("r too large\n");
5625f78d91Sagc return -1;
5725f78d91Sagc }
5825f78d91Sagc (void) memset(to, 0x0, tlen - flen);
5925f78d91Sagc (void) memcpy(to + tlen - flen, from, flen);
6025f78d91Sagc return tlen;
6125f78d91Sagc }
6225f78d91Sagc
6325f78d91Sagc static int
lowlevel_rsa_private_encrypt(int plainc,const unsigned char * plain,unsigned char * encbuf,NETPGPV_RSA * rsa)64472564b2Sagc lowlevel_rsa_private_encrypt(int plainc, const unsigned char *plain, unsigned char *encbuf, NETPGPV_RSA *rsa)
6525f78d91Sagc {
66dd98b26dSagc PGPV_BIGNUM *decbn;
67dd98b26dSagc PGPV_BIGNUM *signedbn;
6825f78d91Sagc uint8_t *decbuf;
6925f78d91Sagc int nbytes;
7025f78d91Sagc int signc;
7125f78d91Sagc int signedbytes;
7225f78d91Sagc int r;
7325f78d91Sagc
7425f78d91Sagc decbuf = NULL;
7525f78d91Sagc r = -1;
76dd98b26dSagc decbn = PGPV_BN_new();
77dd98b26dSagc signedbn = PGPV_BN_new();
78dd98b26dSagc nbytes = PGPV_BN_num_bytes(rsa->n);
7925f78d91Sagc decbuf = netpgp_allocate(1, nbytes);
8025f78d91Sagc /* add no padding */
8125f78d91Sagc memcpy(decbuf, plain, plainc);
82dd98b26dSagc PGPV_BN_bin2bn(decbuf, nbytes, decbn);
83dd98b26dSagc if (PGPV_BN_cmp(decbn, rsa->n) >= 0) {
8425f78d91Sagc printf("decbn too big\n");
8525f78d91Sagc goto err;
8625f78d91Sagc }
87dd98b26dSagc if (!PGPV_BN_mod_exp(signedbn, decbn, rsa->d, rsa->n, NULL)) {
8825f78d91Sagc printf("bad mod_exp\n");
8925f78d91Sagc goto err;
9025f78d91Sagc }
91dd98b26dSagc signedbytes = PGPV_BN_num_bytes(signedbn);
92dd98b26dSagc signc = PGPV_BN_bn2bin(signedbn, &encbuf[nbytes - signedbytes]);
9325f78d91Sagc memset(encbuf, 0x0, nbytes - signc);
9425f78d91Sagc r = nbytes;
9525f78d91Sagc err:
9625f78d91Sagc netpgp_deallocate(decbuf, nbytes);
97dd98b26dSagc PGPV_BN_clear_free(decbn);
98dd98b26dSagc PGPV_BN_clear_free(signedbn);
9925f78d91Sagc return r;
10025f78d91Sagc }
10125f78d91Sagc
10225f78d91Sagc static int
lowlevel_rsa_public_encrypt(int plainc,const unsigned char * plain,unsigned char * encbuf,NETPGPV_RSA * rsa)103472564b2Sagc lowlevel_rsa_public_encrypt(int plainc, const unsigned char *plain, unsigned char *encbuf, NETPGPV_RSA *rsa)
10425f78d91Sagc {
105dd98b26dSagc PGPV_BIGNUM *decbn;
106dd98b26dSagc PGPV_BIGNUM *encbn;
10725f78d91Sagc uint8_t *decbuf;
10825f78d91Sagc int nbytes;
10925f78d91Sagc int encc;
11025f78d91Sagc int r;
11125f78d91Sagc int i;
11225f78d91Sagc
11325f78d91Sagc r = -1;
114dd98b26dSagc decbn = PGPV_BN_new();
115dd98b26dSagc encbn = PGPV_BN_new();
116dd98b26dSagc nbytes = PGPV_BN_num_bytes(rsa->n);
11725f78d91Sagc decbuf = netpgp_allocate(1, nbytes);
11825f78d91Sagc (void) memcpy(decbuf, plain, plainc);
119dd98b26dSagc if (PGPV_BN_bin2bn(decbuf, nbytes, decbn) == NULL) {
12025f78d91Sagc printf("bin2bn failed\n");
12125f78d91Sagc goto err;
12225f78d91Sagc }
123dd98b26dSagc if (PGPV_BN_cmp(decbn, rsa->n) >= 0) {
124dd98b26dSagc printf("PGPV_BN_cmp failed\n");
12525f78d91Sagc goto err;
12625f78d91Sagc }
127dd98b26dSagc if (!PGPV_BN_mod_exp(encbn, decbn, rsa->e, rsa->n, NULL)) {
128dd98b26dSagc printf("PGPV_BN_mod_exp failed\n");
12925f78d91Sagc goto err;
13025f78d91Sagc }
131dd98b26dSagc encc = PGPV_BN_num_bytes(encbn);
132dd98b26dSagc i = PGPV_BN_bn2bin(encbn, &encbuf[nbytes - encc]);
13325f78d91Sagc (void) memset(encbuf, 0x0, nbytes - i);
13425f78d91Sagc r = nbytes;
13525f78d91Sagc err:
13625f78d91Sagc if (decbuf) {
13725f78d91Sagc memset(decbuf, 0x0, nbytes);
13825f78d91Sagc netpgp_deallocate(decbuf, nbytes);
13925f78d91Sagc }
140dd98b26dSagc PGPV_BN_clear_free(decbn);
141dd98b26dSagc PGPV_BN_clear_free(encbn);
14225f78d91Sagc return r;
14325f78d91Sagc }
14425f78d91Sagc
14525f78d91Sagc static int
lowlevel_rsa_private_decrypt(int enclen,const unsigned char * encbuf,unsigned char * to,NETPGPV_RSA * rsa)146472564b2Sagc lowlevel_rsa_private_decrypt(int enclen, const unsigned char *encbuf, unsigned char *to, NETPGPV_RSA *rsa)
14725f78d91Sagc {
148dd98b26dSagc PGPV_BIGNUM *encbn;
149dd98b26dSagc PGPV_BIGNUM *decbn;
15025f78d91Sagc uint8_t *buf;
15125f78d91Sagc int nbytes;
15225f78d91Sagc int j;
15325f78d91Sagc int r;
15425f78d91Sagc
15525f78d91Sagc r = -1;
15625f78d91Sagc decbn = encbn = NULL;
15725f78d91Sagc buf = NULL;
158dd98b26dSagc if (PGPV_BN_num_bits(rsa->n) > RSA_MAX_MODULUS_BITS) {
15925f78d91Sagc return -1;
16025f78d91Sagc }
161dd98b26dSagc if (PGPV_BN_cmp(rsa->n, rsa->e) <= 0) {
16225f78d91Sagc return -1;
16325f78d91Sagc }
164dd98b26dSagc encbn = PGPV_BN_new();
165dd98b26dSagc decbn = PGPV_BN_new();
166dd98b26dSagc nbytes = PGPV_BN_num_bytes(rsa->n);
16725f78d91Sagc buf = netpgp_allocate(1, nbytes);
16825f78d91Sagc if (enclen > nbytes) {
16925f78d91Sagc printf("bad enclen\n");
17025f78d91Sagc goto err;
17125f78d91Sagc }
172dd98b26dSagc PGPV_BN_bin2bn(encbuf, enclen, encbn);
173dd98b26dSagc if (PGPV_BN_cmp(encbn, rsa->n) >= 0) {
17425f78d91Sagc printf("bad encbn\n");
17525f78d91Sagc goto err;
17625f78d91Sagc }
177dd98b26dSagc PGPV_BN_mod_exp(decbn, encbn, rsa->d, rsa->n, NULL);
178dd98b26dSagc j = PGPV_BN_bn2bin(decbn, buf);
17925f78d91Sagc r = rsa_padding_check_none(to, nbytes, buf, j, nbytes);
18025f78d91Sagc err:
181dd98b26dSagc PGPV_BN_clear_free(encbn);
182dd98b26dSagc PGPV_BN_clear_free(decbn);
18325f78d91Sagc netpgp_deallocate(buf, nbytes);
18425f78d91Sagc return r;
18525f78d91Sagc }
18625f78d91Sagc
18725f78d91Sagc static int
lowlevel_rsa_public_decrypt(const uint8_t * encbuf,int enclen,uint8_t * dec,const netpgpv_rsa_pubkey_t * rsa)188472564b2Sagc lowlevel_rsa_public_decrypt(const uint8_t *encbuf, int enclen, uint8_t *dec, const netpgpv_rsa_pubkey_t *rsa)
18925f78d91Sagc {
19025f78d91Sagc uint8_t *decbuf;
191dd98b26dSagc PGPV_BIGNUM *decbn;
192dd98b26dSagc PGPV_BIGNUM *encbn;
19325f78d91Sagc int decbytes;
19425f78d91Sagc int nbytes;
19525f78d91Sagc int r;
19625f78d91Sagc
19725f78d91Sagc nbytes = 0;
19825f78d91Sagc r = -1;
19925f78d91Sagc decbuf = NULL;
20025f78d91Sagc decbn = encbn = NULL;
201dd98b26dSagc if (PGPV_BN_num_bits(rsa->n) > RSA_MAX_MODULUS_BITS) {
20225f78d91Sagc printf("rsa r modulus too large\n");
20325f78d91Sagc goto err;
20425f78d91Sagc }
205dd98b26dSagc if (PGPV_BN_cmp(rsa->n, rsa->e) <= 0) {
20625f78d91Sagc printf("rsa r bad n value\n");
20725f78d91Sagc goto err;
20825f78d91Sagc }
209dd98b26dSagc if (PGPV_BN_num_bits(rsa->n) > RSA_SMALL_MODULUS_BITS &&
210dd98b26dSagc PGPV_BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS) {
21125f78d91Sagc printf("rsa r bad exponent limit\n");
21225f78d91Sagc goto err;
21325f78d91Sagc }
214dd98b26dSagc if ((encbn = PGPV_BN_new()) == NULL ||
215dd98b26dSagc (decbn = PGPV_BN_new()) == NULL ||
216dd98b26dSagc (decbuf = netpgp_allocate(1, nbytes = PGPV_BN_num_bytes(rsa->n))) == NULL) {
21725f78d91Sagc printf("allocation failure\n");
21825f78d91Sagc goto err;
21925f78d91Sagc }
22025f78d91Sagc if (enclen > nbytes) {
22125f78d91Sagc printf("rsa r > mod len\n");
22225f78d91Sagc goto err;
22325f78d91Sagc }
224dd98b26dSagc if (PGPV_BN_bin2bn(encbuf, enclen, encbn) == NULL) {
22525f78d91Sagc printf("null encrypted BN\n");
22625f78d91Sagc goto err;
22725f78d91Sagc }
228dd98b26dSagc if (PGPV_BN_cmp(encbn, rsa->n) >= 0) {
22925f78d91Sagc printf("rsa r data too large for modulus\n");
23025f78d91Sagc goto err;
23125f78d91Sagc }
232dd98b26dSagc if (PGPV_BN_mod_exp(decbn, encbn, rsa->e, rsa->n, NULL) < 0) {
233dd98b26dSagc printf("PGPV_BN_mod_exp < 0\n");
23425f78d91Sagc goto err;
23525f78d91Sagc }
236dd98b26dSagc decbytes = PGPV_BN_num_bytes(decbn);
237dd98b26dSagc (void) PGPV_BN_bn2bin(decbn, decbuf);
23825f78d91Sagc if ((r = rsa_padding_check_none(dec, nbytes, decbuf, decbytes, 0)) < 0) {
23925f78d91Sagc printf("rsa r padding check failed\n");
24025f78d91Sagc }
24125f78d91Sagc err:
242dd98b26dSagc PGPV_BN_free(encbn);
243dd98b26dSagc PGPV_BN_free(decbn);
24425f78d91Sagc if (decbuf != NULL) {
24525f78d91Sagc (void) memset(decbuf, 0x0, nbytes);
24625f78d91Sagc netpgp_deallocate(decbuf, nbytes);
24725f78d91Sagc }
24825f78d91Sagc return r;
24925f78d91Sagc }
25025f78d91Sagc
25125f78d91Sagc #if 0
25225f78d91Sagc /**
25325f78d91Sagc @file rsa_make_key.c
25425f78d91Sagc RSA key generation, Tom St Denis
25525f78d91Sagc */
25625f78d91Sagc
25725f78d91Sagc /**
25825f78d91Sagc Create an RSA key
25925f78d91Sagc @param prng An active PRNG state
26025f78d91Sagc @param wprng The index of the PRNG desired
26125f78d91Sagc @param size The size of the modulus (key size) desired (octets)
26225f78d91Sagc @param e The "e" value (public key). e==65537 is a good choice
26325f78d91Sagc @param key [out] Destination of a newly created private key pair
26425f78d91Sagc @return CRYPT_OK if successful, upon error all allocated ram is freed
26525f78d91Sagc */
26625f78d91Sagc static int
26725f78d91Sagc rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
26825f78d91Sagc {
26925f78d91Sagc void *p, *q, *tmp1, *tmp2, *tmp3;
27025f78d91Sagc int err;
27125f78d91Sagc
27225f78d91Sagc LTC_ARGCHK(ltc_mp.name != NULL);
27325f78d91Sagc LTC_ARGCHK(key != NULL);
27425f78d91Sagc
27525f78d91Sagc if ((size < (MIN_RSA_SIZE/8)) || (size > (MAX_RSA_SIZE/8))) {
27625f78d91Sagc return CRYPT_INVALID_KEYSIZE;
27725f78d91Sagc }
27825f78d91Sagc
27925f78d91Sagc if ((e < 3) || ((e & 1) == 0)) {
28025f78d91Sagc return CRYPT_INVALID_ARG;
28125f78d91Sagc }
28225f78d91Sagc
28325f78d91Sagc if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
28425f78d91Sagc return err;
28525f78d91Sagc }
28625f78d91Sagc
28725f78d91Sagc if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != CRYPT_OK) {
28825f78d91Sagc return err;
28925f78d91Sagc }
29025f78d91Sagc
29125f78d91Sagc /* make primes p and q (optimization provided by Wayne Scott) */
29225f78d91Sagc /* tmp3 = e */
29325f78d91Sagc if ((err = mp_set_int(tmp3, e)) != CRYPT_OK) {
29425f78d91Sagc goto errkey;
29525f78d91Sagc }
29625f78d91Sagc
29725f78d91Sagc /* make prime "p" */
29825f78d91Sagc do {
29925f78d91Sagc if ((err = rand_prime( p, size/2, prng, wprng)) != CRYPT_OK) {
30025f78d91Sagc goto errkey;
30125f78d91Sagc }
30225f78d91Sagc /* tmp1 = p-1 */
30325f78d91Sagc if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) {
30425f78d91Sagc goto errkey;
30525f78d91Sagc }
30625f78d91Sagc /* tmp2 = gcd(p-1, e) */
30725f78d91Sagc if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) {
30825f78d91Sagc goto errkey;
30925f78d91Sagc }
31025f78d91Sagc } while (mp_cmp_d( tmp2, 1) != 0);
31125f78d91Sagc /* while e divides p-1 */
31225f78d91Sagc
31325f78d91Sagc /* make prime "q" */
31425f78d91Sagc do {
31525f78d91Sagc if ((err = rand_prime( q, size/2, prng, wprng)) != CRYPT_OK) {
31625f78d91Sagc goto errkey;
31725f78d91Sagc }
31825f78d91Sagc /* tmp1 = q-1 */
31925f78d91Sagc if ((err = mp_sub_d( q, 1, tmp1)) != CRYPT_OK) {
32025f78d91Sagc goto errkey;
32125f78d91Sagc }
32225f78d91Sagc /* tmp2 = gcd(q-1, e) */
32325f78d91Sagc if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) {
32425f78d91Sagc goto errkey;
32525f78d91Sagc }
32625f78d91Sagc } while (mp_cmp_d( tmp2, 1) != 0);
32725f78d91Sagc /* while e divides q-1 */
32825f78d91Sagc
32925f78d91Sagc /* tmp1 = lcm(p-1, q-1) */
33025f78d91Sagc /* tmp2 = p-1 */
33125f78d91Sagc if ((err = mp_sub_d( p, 1, tmp2)) != CRYPT_OK) {
33225f78d91Sagc goto errkey;
33325f78d91Sagc }
33425f78d91Sagc /* tmp1 = q-1 (previous do/while loop) */
33525f78d91Sagc /* tmp1 = lcm(p-1, q-1) */
33625f78d91Sagc if ((err = mp_lcm( tmp1, tmp2, tmp1)) != CRYPT_OK) {
33725f78d91Sagc goto errkey;
33825f78d91Sagc }
33925f78d91Sagc
34025f78d91Sagc /* make key */
34125f78d91Sagc if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {
34225f78d91Sagc goto errkey;
34325f78d91Sagc }
34425f78d91Sagc
34525f78d91Sagc /* key->e = e */
34625f78d91Sagc if ((err = mp_set_int( key->e, e)) != CRYPT_OK) {
34725f78d91Sagc goto errkey;
34825f78d91Sagc }
34925f78d91Sagc /* key->d = 1/e mod lcm(p-1,q-1) */
35025f78d91Sagc if ((err = mp_invmod( key->e, tmp1, key->d)) != CRYPT_OK) {
35125f78d91Sagc goto errkey;
35225f78d91Sagc }
35325f78d91Sagc /* key->N = pq */
35425f78d91Sagc if ((err = mp_mul( p, q, key->N)) != CRYPT_OK) {
35525f78d91Sagc goto errkey;
35625f78d91Sagc }
35725f78d91Sagc
35825f78d91Sagc /* optimize for CRT now */
35925f78d91Sagc /* find d mod q-1 and d mod p-1 */
36025f78d91Sagc /* tmp1 = q-1 */
36125f78d91Sagc if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) {
36225f78d91Sagc goto errkey;
36325f78d91Sagc }
36425f78d91Sagc /* tmp2 = p-1 */
36525f78d91Sagc if ((err = mp_sub_d( q, 1, tmp2)) != CRYPT_OK) {
36625f78d91Sagc goto errkey;
36725f78d91Sagc }
36825f78d91Sagc /* dP = d mod p-1 */
36925f78d91Sagc if ((err = mp_mod( key->d, tmp1, key->dP)) != CRYPT_OK) {
37025f78d91Sagc goto errkey;
37125f78d91Sagc }
37225f78d91Sagc /* dQ = d mod q-1 */
37325f78d91Sagc if ((err = mp_mod( key->d, tmp2, key->dQ)) != CRYPT_OK) {
37425f78d91Sagc goto errkey;
37525f78d91Sagc }
37625f78d91Sagc /* qP = 1/q mod p */
37725f78d91Sagc if ((err = mp_invmod( q, p, key->qP)) != CRYPT_OK) {
37825f78d91Sagc got oerrkey;
37925f78d91Sagc }
38025f78d91Sagc
38125f78d91Sagc if ((err = mp_copy( p, key->p)) != CRYPT_OK) {
38225f78d91Sagc goto errkey;
38325f78d91Sagc }
38425f78d91Sagc if ((err = mp_copy( q, key->q)) != CRYPT_OK) {
38525f78d91Sagc goto errkey;
38625f78d91Sagc }
38725f78d91Sagc
38825f78d91Sagc /* set key type (in this case it's CRT optimized) */
38925f78d91Sagc key->type = PK_PRIVATE;
39025f78d91Sagc
39125f78d91Sagc /* return ok and free temps */
39225f78d91Sagc err = CRYPT_OK;
39325f78d91Sagc goto cleanup;
39425f78d91Sagc errkey:
39525f78d91Sagc mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
39625f78d91Sagc cleanup:
39725f78d91Sagc mp_clear_multi(tmp3, tmp2, tmp1, p, q, NULL);
39825f78d91Sagc return err;
39925f78d91Sagc }
40025f78d91Sagc #endif
40125f78d91Sagc
40225f78d91Sagc #define HASHBUF_LEN 512
40325f78d91Sagc
40425f78d91Sagc #define DSA_MAX_MODULUS_BITS 10000
40525f78d91Sagc
40625f78d91Sagc static int
dsa_do_verify(const unsigned char * calculated,int dgst_len,const netpgpv_dsasig_t * sig,netpgpv_mpi_dsa_t * dsa)407472564b2Sagc dsa_do_verify(const unsigned char *calculated, int dgst_len, const netpgpv_dsasig_t *sig, netpgpv_mpi_dsa_t *dsa)
40825f78d91Sagc {
409dd98b26dSagc PGPV_BIGNUM *M;
410dd98b26dSagc PGPV_BIGNUM *W;
411dd98b26dSagc PGPV_BIGNUM *t1;
41225f78d91Sagc int ret = -1;
41325f78d91Sagc int qbits;
41425f78d91Sagc
41525f78d91Sagc if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
41625f78d91Sagc return 0;
41725f78d91Sagc }
41825f78d91Sagc M = W = t1 = NULL;
419dd98b26dSagc qbits = PGPV_BN_num_bits(dsa->q);
42025f78d91Sagc switch(qbits) {
42125f78d91Sagc case 160:
42225f78d91Sagc case 224:
42325f78d91Sagc case 256:
42425f78d91Sagc /* openssl sources say these are the valid values */
42525f78d91Sagc /* according to FIPS 186-3 */
42625f78d91Sagc break;
42725f78d91Sagc default:
42825f78d91Sagc printf("dsa: bad # of Q bits\n");
42925f78d91Sagc return 0;
43025f78d91Sagc }
431dd98b26dSagc if (PGPV_BN_num_bits(dsa->p) > DSA_MAX_MODULUS_BITS) {
43225f78d91Sagc printf("dsa: p too large\n");
43325f78d91Sagc return 0;
43425f78d91Sagc }
43525f78d91Sagc /* no love for SHA512? */
43625f78d91Sagc if (dgst_len > SHA256_DIGEST_LENGTH) {
43725f78d91Sagc printf("dsa: digest too long\n");
43825f78d91Sagc return 0;
43925f78d91Sagc }
44025f78d91Sagc ret = 0;
441dd98b26dSagc if ((M = PGPV_BN_new()) == NULL ||
442dd98b26dSagc (W = PGPV_BN_new()) == NULL ||
443dd98b26dSagc (t1 = PGPV_BN_new()) == NULL) {
44425f78d91Sagc goto err;
44525f78d91Sagc }
446dd98b26dSagc if (PGPV_BN_is_zero(sig->r) ||
447dd98b26dSagc PGPV_BN_is_negative(sig->r) ||
448dd98b26dSagc PGPV_BN_cmp(sig->r, dsa->q) >= 0) {
44925f78d91Sagc goto err;
45025f78d91Sagc }
451dd98b26dSagc if (PGPV_BN_is_zero(sig->s) ||
452dd98b26dSagc PGPV_BN_is_negative(sig->s) ||
453dd98b26dSagc PGPV_BN_cmp(sig->s, dsa->q) >= 0) {
45425f78d91Sagc goto err;
45525f78d91Sagc }
456dd98b26dSagc if (PGPV_BN_mod_inverse(W, sig->s, dsa->q, NULL) != MP_OKAY) {
45725f78d91Sagc goto err;
45825f78d91Sagc }
45925f78d91Sagc if (dgst_len > qbits / 8) {
46025f78d91Sagc dgst_len = qbits / 8;
46125f78d91Sagc }
462dd98b26dSagc if (PGPV_BN_bin2bn(calculated, dgst_len, M) == NULL) {
46325f78d91Sagc goto err;
46425f78d91Sagc }
465dd98b26dSagc if (!PGPV_BN_mod_mul(M, M, W, dsa->q, NULL)) {
46625f78d91Sagc goto err;
46725f78d91Sagc }
468dd98b26dSagc if (!PGPV_BN_mod_mul(W, sig->r, W, dsa->q, NULL)) {
46925f78d91Sagc goto err;
47025f78d91Sagc }
471dd98b26dSagc if (!PGPV_BN_mod_exp(dsa->p, t1, dsa->g, M, NULL)) {
47225f78d91Sagc goto err;
47325f78d91Sagc }
474dd98b26dSagc if (!PGPV_BN_div(NULL, M, t1, dsa->q, NULL)) {
47525f78d91Sagc goto err;
47625f78d91Sagc }
477dd98b26dSagc ret = (PGPV_BN_cmp(M, sig->r) == 0);
47825f78d91Sagc err:
47925f78d91Sagc if (M) {
480dd98b26dSagc PGPV_BN_free(M);
48125f78d91Sagc }
48225f78d91Sagc if (W) {
483dd98b26dSagc PGPV_BN_free(W);
48425f78d91Sagc }
48525f78d91Sagc if (t1) {
486dd98b26dSagc PGPV_BN_free(t1);
48725f78d91Sagc }
48825f78d91Sagc return ret;
48925f78d91Sagc }
49025f78d91Sagc
49125f78d91Sagc /*************************************************************************/
49225f78d91Sagc
49325f78d91Sagc int
netpgpv_RSA_size(const NETPGPV_RSA * rsa)494472564b2Sagc netpgpv_RSA_size(const NETPGPV_RSA *rsa)
49525f78d91Sagc {
496dd98b26dSagc return (rsa == NULL) ? 0 : PGPV_BN_num_bits(rsa->n);
49725f78d91Sagc }
49825f78d91Sagc
49925f78d91Sagc int
netpgpv_DSA_size(const NETPGPV_DSA * dsa)500472564b2Sagc netpgpv_DSA_size(const NETPGPV_DSA *dsa)
50125f78d91Sagc {
502dd98b26dSagc return (dsa == NULL) ? 0 : PGPV_BN_num_bits(dsa->p);
50325f78d91Sagc }
50425f78d91Sagc
50525f78d91Sagc unsigned
netpgpv_dsa_verify(const signature_t * signature,const netpgpv_dsa_pubkey_t * pubdsa,const uint8_t * calculated,size_t hash_length)506472564b2Sagc netpgpv_dsa_verify(const signature_t *signature,
507472564b2Sagc const netpgpv_dsa_pubkey_t *pubdsa, const uint8_t *calculated,
508472564b2Sagc size_t hash_length)
50925f78d91Sagc {
510472564b2Sagc netpgpv_mpi_dsa_t odsa;
511472564b2Sagc netpgpv_dsasig_t osig;
51225f78d91Sagc unsigned qlen;
51325f78d91Sagc int ret;
51425f78d91Sagc
51525f78d91Sagc if (signature == NULL || pubdsa == NULL || calculated == NULL) {
516*05c460adSrillig return (unsigned)-1;
51725f78d91Sagc }
51825f78d91Sagc (void) memset(&osig, 0x0, sizeof(osig));
51925f78d91Sagc (void) memset(&odsa, 0x0, sizeof(odsa));
520dd98b26dSagc PGPV_BN_copy(osig.r, signature->dsa.r);
521dd98b26dSagc PGPV_BN_copy(osig.s, signature->dsa.s);
52225f78d91Sagc odsa.p = pubdsa->p;
52325f78d91Sagc odsa.q = pubdsa->q;
52425f78d91Sagc odsa.g = pubdsa->g;
52525f78d91Sagc odsa.pub_key = pubdsa->y;
526dd98b26dSagc if ((qlen = PGPV_BN_num_bytes(odsa.q)) < hash_length) {
52725f78d91Sagc hash_length = qlen;
52825f78d91Sagc }
52925f78d91Sagc ret = dsa_do_verify(calculated, (int)hash_length, &signature->dsa, &odsa);
53025f78d91Sagc if (ret < 0) {
53125f78d91Sagc return 0;
53225f78d91Sagc }
533dd98b26dSagc PGPV_BN_free(odsa.p);
534dd98b26dSagc PGPV_BN_free(odsa.q);
535dd98b26dSagc PGPV_BN_free(odsa.g);
536dd98b26dSagc PGPV_BN_free(odsa.pub_key);
53725f78d91Sagc odsa.p = odsa.q = odsa.g = odsa.pub_key = NULL;
538dd98b26dSagc PGPV_BN_free(osig.r);
539dd98b26dSagc PGPV_BN_free(osig.s);
54025f78d91Sagc osig.r = osig.s = NULL;
54125f78d91Sagc return (unsigned)ret;
54225f78d91Sagc }
54325f78d91Sagc
544472564b2Sagc NETPGPV_RSA *
netpgpv_RSA_new(void)545472564b2Sagc netpgpv_RSA_new(void)
54625f78d91Sagc {
547472564b2Sagc return netpgp_allocate(1, sizeof(NETPGPV_RSA));
54825f78d91Sagc }
54925f78d91Sagc
55025f78d91Sagc void
netpgpv_RSA_free(NETPGPV_RSA * rsa)551472564b2Sagc netpgpv_RSA_free(NETPGPV_RSA *rsa)
55225f78d91Sagc {
55325f78d91Sagc if (rsa) {
55425f78d91Sagc netpgp_deallocate(rsa, sizeof(*rsa));
55525f78d91Sagc }
55625f78d91Sagc }
55725f78d91Sagc
55825f78d91Sagc int
netpgpv_RSA_check_key(NETPGPV_RSA * rsa)559472564b2Sagc netpgpv_RSA_check_key(NETPGPV_RSA *rsa)
56025f78d91Sagc {
561dd98b26dSagc PGPV_BIGNUM *calcn;
56225f78d91Sagc int ret;
56325f78d91Sagc
56425f78d91Sagc ret = 0;
56525f78d91Sagc if (rsa == NULL || rsa->p == NULL || rsa->q == NULL || rsa->n == NULL) {
56625f78d91Sagc return -1;
56725f78d91Sagc }
56825f78d91Sagc /* check that p and q are coprime, and that n = p*q. */
569dd98b26dSagc if (!PGPV_BN_is_prime(rsa->p, 1, NULL, NULL, NULL) ||
570dd98b26dSagc !PGPV_BN_is_prime(rsa->q, 1, NULL, NULL, NULL)) {
57125f78d91Sagc return 0;
57225f78d91Sagc }
573dd98b26dSagc calcn = PGPV_BN_new();
574dd98b26dSagc PGPV_BN_mul(calcn, rsa->p, rsa->q, NULL);
575dd98b26dSagc if (PGPV_BN_cmp(calcn, rsa->n) != 0) {
57625f78d91Sagc goto errout;
57725f78d91Sagc }
57825f78d91Sagc /* XXX - check that d*e = 1 mod (p-1*q-1) */
57925f78d91Sagc ret = 1;
58025f78d91Sagc errout:
581dd98b26dSagc PGPV_BN_clear_free(calcn);
58225f78d91Sagc return ret;
58325f78d91Sagc }
58425f78d91Sagc
585472564b2Sagc NETPGPV_RSA *
netpgpv_RSA_generate_key(int num,unsigned long e,void (* callback)(int,int,void *),void * cb_arg)586472564b2Sagc netpgpv_RSA_generate_key(int num, unsigned long e, void (*callback)(int,int,void *), void *cb_arg)
58725f78d91Sagc {
58825f78d91Sagc /* STUBBED */
58925f78d91Sagc USE_ARG(num);
59025f78d91Sagc USE_ARG(e);
59125f78d91Sagc USE_ARG(callback);
59225f78d91Sagc USE_ARG(cb_arg);
59325f78d91Sagc printf("RSA_generate_key stubbed\n");
594472564b2Sagc return netpgpv_RSA_new();
59525f78d91Sagc }
59625f78d91Sagc
59725f78d91Sagc /* encrypt */
59825f78d91Sagc int
netpgpv_RSA_public_encrypt(int plainc,const unsigned char * plain,unsigned char * encbuf,NETPGPV_RSA * rsa,int padding)599472564b2Sagc netpgpv_RSA_public_encrypt(int plainc, const unsigned char *plain, unsigned char *encbuf, NETPGPV_RSA *rsa, int padding)
60025f78d91Sagc {
60125f78d91Sagc USE_ARG(padding);
60225f78d91Sagc if (plain == NULL || encbuf == NULL || rsa == NULL) {
60325f78d91Sagc return -1;
60425f78d91Sagc }
60525f78d91Sagc return lowlevel_rsa_public_encrypt(plainc, plain, encbuf, rsa);
60625f78d91Sagc }
60725f78d91Sagc
60825f78d91Sagc /* decrypt */
60925f78d91Sagc int
netpgpv_RSA_private_decrypt(int flen,const unsigned char * from,unsigned char * to,NETPGPV_RSA * rsa,int padding)610472564b2Sagc netpgpv_RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to, NETPGPV_RSA *rsa, int padding)
61125f78d91Sagc {
61225f78d91Sagc USE_ARG(padding);
61325f78d91Sagc if (from == NULL || to == NULL || rsa == NULL) {
61425f78d91Sagc return -1;
61525f78d91Sagc }
61625f78d91Sagc return lowlevel_rsa_private_decrypt(flen, from, to, rsa);
61725f78d91Sagc }
61825f78d91Sagc
61925f78d91Sagc /* sign */
62025f78d91Sagc int
netpgpv_RSA_private_encrypt(int plainc,const unsigned char * plain,unsigned char * encbuf,NETPGPV_RSA * rsa,int padding)621472564b2Sagc netpgpv_RSA_private_encrypt(int plainc, const unsigned char *plain, unsigned char *encbuf, NETPGPV_RSA *rsa, int padding)
62225f78d91Sagc {
62325f78d91Sagc USE_ARG(padding);
62425f78d91Sagc if (plain == NULL || encbuf == NULL || rsa == NULL) {
62525f78d91Sagc return -1;
62625f78d91Sagc }
62725f78d91Sagc return lowlevel_rsa_private_encrypt(plainc, plain, encbuf, rsa);
62825f78d91Sagc }
62925f78d91Sagc
63025f78d91Sagc /* verify */
63125f78d91Sagc int
netpgpv_RSA_public_decrypt(int enclen,const unsigned char * enc,unsigned char * dec,NETPGPV_RSA * rsa,int padding)632472564b2Sagc netpgpv_RSA_public_decrypt(int enclen, const unsigned char *enc, unsigned char *dec, NETPGPV_RSA *rsa, int padding)
63325f78d91Sagc {
634472564b2Sagc netpgpv_rsa_pubkey_t pub;
63525f78d91Sagc int ret;
63625f78d91Sagc
63725f78d91Sagc if (enc == NULL || dec == NULL || rsa == NULL) {
63825f78d91Sagc return 0;
63925f78d91Sagc }
64025f78d91Sagc USE_ARG(padding);
64125f78d91Sagc (void) memset(&pub, 0x0, sizeof(pub));
642dd98b26dSagc pub.n = PGPV_BN_dup(rsa->n);
643dd98b26dSagc pub.e = PGPV_BN_dup(rsa->e);
64425f78d91Sagc ret = lowlevel_rsa_public_decrypt(enc, enclen, dec, &pub);
645dd98b26dSagc PGPV_BN_free(pub.n);
646dd98b26dSagc PGPV_BN_free(pub.e);
64725f78d91Sagc return ret;
64825f78d91Sagc }
64925f78d91Sagc
65025f78d91Sagc /***********************************************************************/
65125f78d91Sagc
652472564b2Sagc NETPGPV_DSA *
netpgpv_DSA_new(void)653472564b2Sagc netpgpv_DSA_new(void)
65425f78d91Sagc {
655472564b2Sagc return netpgp_allocate(1, sizeof(NETPGPV_DSA));
65625f78d91Sagc }
65725f78d91Sagc
65825f78d91Sagc void
netpgpv_DSA_free(NETPGPV_DSA * dsa)659472564b2Sagc netpgpv_DSA_free(NETPGPV_DSA *dsa)
66025f78d91Sagc {
66125f78d91Sagc if (dsa) {
66225f78d91Sagc netpgp_deallocate(dsa, sizeof(*dsa));
66325f78d91Sagc }
66425f78d91Sagc }
66525f78d91Sagc
666472564b2Sagc NETPGPV_DSA_SIG *
netpgpv_DSA_SIG_new(void)667472564b2Sagc netpgpv_DSA_SIG_new(void)
66825f78d91Sagc {
669472564b2Sagc return netpgp_allocate(1, sizeof(NETPGPV_DSA_SIG));
67025f78d91Sagc }
67125f78d91Sagc
67225f78d91Sagc void
netpgpv_DSA_SIG_free(NETPGPV_DSA_SIG * sig)673472564b2Sagc netpgpv_DSA_SIG_free(NETPGPV_DSA_SIG *sig)
67425f78d91Sagc {
67525f78d91Sagc if (sig) {
67625f78d91Sagc netpgp_deallocate(sig, sizeof(*sig));
67725f78d91Sagc }
67825f78d91Sagc }
67925f78d91Sagc
680472564b2Sagc NETPGPV_DSA_SIG *
netpgpv_DSA_do_sign(const unsigned char * dgst,int dlen,NETPGPV_DSA * dsa)681472564b2Sagc netpgpv_DSA_do_sign(const unsigned char *dgst, int dlen, NETPGPV_DSA *dsa)
68225f78d91Sagc {
68325f78d91Sagc /* STUBBED */
68425f78d91Sagc USE_ARG(dgst);
68525f78d91Sagc USE_ARG(dlen);
68625f78d91Sagc USE_ARG(dsa);
68725f78d91Sagc printf("DSA_do_sign stubbed\n");
688472564b2Sagc return netpgpv_DSA_SIG_new();
68925f78d91Sagc }
69025f78d91Sagc
69125f78d91Sagc int
netpgpv_DSA_do_verify(const unsigned char * dgst,int dgst_len,NETPGPV_DSA_SIG * sig,NETPGPV_DSA * dsa)692472564b2Sagc netpgpv_DSA_do_verify(const unsigned char *dgst, int dgst_len, NETPGPV_DSA_SIG *sig, NETPGPV_DSA *dsa)
69325f78d91Sagc {
69425f78d91Sagc if (dgst == NULL || dgst_len == 0 || sig == NULL || dsa == NULL) {
69525f78d91Sagc return -1;
69625f78d91Sagc }
69725f78d91Sagc return dsa_do_verify(dgst, dgst_len, sig, dsa);
69825f78d91Sagc }
699