DH facelift part1
This commit is contained in:
+36
-24
@@ -183,45 +183,57 @@ int katja_import(const unsigned char *in, unsigned long inlen, katja_key *key);
|
||||
/* ---- DH Routines ---- */
|
||||
#ifdef LTC_MDH
|
||||
|
||||
typedef struct Dh_key {
|
||||
int idx, type;
|
||||
#ifndef DH_BUF_SIZE
|
||||
#define DH_BUF_SIZE 2100
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
char *name, *base, *prime;
|
||||
} ltc_dh_set_type;
|
||||
|
||||
extern const ltc_dh_set_type ltc_dh_sets[];
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
void *x;
|
||||
void *y;
|
||||
void *base;
|
||||
void *prime;
|
||||
} dh_key;
|
||||
|
||||
int dh_compat_test(void);
|
||||
void dh_sizes(int *low, int *high);
|
||||
int dh_get_size(dh_key *key);
|
||||
int dh_get_groupsize(dh_key *key);
|
||||
|
||||
int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key);
|
||||
int dh_make_key(prng_state *prng, int wprng, int groupsize, dh_key *key);
|
||||
int dh_make_key_ex(prng_state *prng, int wprng, int radix,
|
||||
void *prime, unsigned long primelen,
|
||||
void *base, unsigned long baselen,
|
||||
dh_key *key);
|
||||
int dh_make_key_dhparam(prng_state *prng, int wprng, unsigned char *dhparam, unsigned long dhparamlen, dh_key *key);
|
||||
void dh_free(dh_key *key);
|
||||
|
||||
int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key);
|
||||
int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key);
|
||||
|
||||
int dh_export_radix(int radix,
|
||||
void *out, unsigned long *outlen,
|
||||
int type, dh_key *key);
|
||||
int dh_import_radix(int radix,
|
||||
void *in, unsigned long inlen,
|
||||
void *prime, unsigned long primelen,
|
||||
void *base, unsigned long baselen,
|
||||
int type, dh_key *key);
|
||||
|
||||
int dh_shared_secret(dh_key *private_key, dh_key *public_key,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int dh_encrypt_key(const unsigned char *in, unsigned long keylen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
prng_state *prng, int wprng, int hash,
|
||||
dh_key *key);
|
||||
|
||||
int dh_decrypt_key(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
dh_key *key);
|
||||
|
||||
int dh_sign_hash(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
prng_state *prng, int wprng, dh_key *key);
|
||||
|
||||
int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
|
||||
const unsigned char *hash, unsigned long hashlen,
|
||||
int *stat, dh_key *key);
|
||||
|
||||
|
||||
#ifdef LTC_SOURCE
|
||||
/* INTERNAL ONLY - it should be later moved to src/headers/tomcrypt_internal.h */
|
||||
int dh_check_pubkey(dh_key *key);
|
||||
#endif
|
||||
|
||||
#endif /* LTC_MDH */
|
||||
|
||||
|
||||
/* ---- ECC Routines ---- */
|
||||
#ifdef LTC_MECC
|
||||
|
||||
+215
-384
@@ -5,402 +5,233 @@
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
|
||||
*/
|
||||
#include "tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file dh.c
|
||||
DH crypto, Tom St Denis
|
||||
*/
|
||||
#include "tomcrypt.h"
|
||||
|
||||
#ifdef LTC_MDH
|
||||
|
||||
|
||||
#include "dh_static.h"
|
||||
|
||||
/**
|
||||
Test the DH sub-system (can take a while)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int dh_compat_test(void)
|
||||
{
|
||||
void *p, *g, *tmp;
|
||||
int x, err, primality;
|
||||
|
||||
if ((err = mp_init_multi(&p, &g, &tmp, NULL)) != CRYPT_OK) { goto error; }
|
||||
|
||||
for (x = 0; sets[x].size != 0; x++) {
|
||||
#if 0
|
||||
printf("dh_test():testing size %d-bits\n", sets[x].size * 8);
|
||||
/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */
|
||||
const ltc_dh_set_type ltc_dh_sets[] = {
|
||||
#ifdef LTC_DH768
|
||||
{ /* 768-bit MODP Group 1 - https://tools.ietf.org/html/rfc7296#appendix-B.1 */
|
||||
96,
|
||||
"DH-768",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
#ifdef LTC_DH1024
|
||||
{ /* 1024-bit MODP Group 2 - https://tools.ietf.org/html/rfc7296#appendix-B.2 */
|
||||
128,
|
||||
"DH-1024",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
|
||||
"FFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
#ifdef LTC_DH1536
|
||||
{ /* 1536-bit MODP Group 5 - https://tools.ietf.org/html/rfc3526#section-2 */
|
||||
192,
|
||||
"DH-1536",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
"670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
#ifdef LTC_DH2048
|
||||
{ /* 2048-bit MODP Group 14 - https://tools.ietf.org/html/rfc3526#section-3 */
|
||||
256,
|
||||
"DH-2048",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
|
||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
|
||||
"15728E5A8AACAA68FFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
#ifdef LTC_DH3072
|
||||
{ /* 3072-bit MODP Group 15 - https://tools.ietf.org/html/rfc3526#section-4 */
|
||||
384,
|
||||
"DH-3072",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
|
||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
|
||||
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
|
||||
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
|
||||
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
|
||||
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
|
||||
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
|
||||
"43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
#ifdef LTC_DH4096
|
||||
{ /* 4096-bit MODP Group 16 - https://tools.ietf.org/html/rfc3526#section-5 */
|
||||
512,
|
||||
"DH-4096",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
|
||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
|
||||
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
|
||||
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
|
||||
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
|
||||
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
|
||||
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
|
||||
"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
|
||||
"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
|
||||
"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
|
||||
"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
|
||||
"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
|
||||
"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
|
||||
"FFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
#ifdef LTC_DH6144
|
||||
{ /* 6144-bit MODP Group 17 - https://tools.ietf.org/html/rfc3526#section-6 */
|
||||
768,
|
||||
"DH-6144",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
|
||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
|
||||
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
|
||||
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
|
||||
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
|
||||
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
|
||||
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
|
||||
"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
|
||||
"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
|
||||
"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
|
||||
"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
|
||||
"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
|
||||
"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
|
||||
"36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
|
||||
"F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
|
||||
"179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
|
||||
"DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
|
||||
"5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
|
||||
"D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
|
||||
"23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
|
||||
"CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
|
||||
"06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
|
||||
"DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
|
||||
"12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
#ifdef LTC_DH8192
|
||||
{ /* 8192-bit MODP Group 18 - https://tools.ietf.org/html/rfc3526#section-7 */
|
||||
1024,
|
||||
"DH-8192",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
|
||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
|
||||
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
|
||||
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
|
||||
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
|
||||
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
|
||||
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
|
||||
"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
|
||||
"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
|
||||
"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
|
||||
"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
|
||||
"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
|
||||
"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
|
||||
"36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
|
||||
"F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
|
||||
"179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
|
||||
"DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
|
||||
"5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
|
||||
"D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
|
||||
"23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
|
||||
"CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
|
||||
"06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
|
||||
"DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
|
||||
"12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4"
|
||||
"38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300"
|
||||
"741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568"
|
||||
"3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
|
||||
"22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B"
|
||||
"4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A"
|
||||
"062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36"
|
||||
"4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1"
|
||||
"B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92"
|
||||
"4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47"
|
||||
"9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71"
|
||||
"60C980DD98EDD3DFFFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
if ((err = mp_read_radix(g,(char *)sets[x].base, 16)) != CRYPT_OK) { goto error; }
|
||||
if ((err = mp_read_radix(p,(char *)sets[x].prime, 16)) != CRYPT_OK) { goto error; }
|
||||
|
||||
/* ensure p is prime */
|
||||
if ((err = mp_prime_is_prime(p, 8, &primality)) != CRYPT_OK) { goto done; }
|
||||
if (primality != LTC_MP_YES ) {
|
||||
err = CRYPT_FAIL_TESTVECTOR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((err = mp_sub_d(p, 1, tmp)) != CRYPT_OK) { goto error; }
|
||||
if ((err = mp_div_2(tmp, tmp)) != CRYPT_OK) { goto error; }
|
||||
|
||||
/* ensure (p-1)/2 is prime */
|
||||
if ((err = mp_prime_is_prime(tmp, 8, &primality)) != CRYPT_OK) { goto done; }
|
||||
if (primality == 0) {
|
||||
err = CRYPT_FAIL_TESTVECTOR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* now see if g^((p-1)/2) mod p is in fact 1 */
|
||||
if ((err = mp_exptmod(g, tmp, p, tmp)) != CRYPT_OK) { goto error; }
|
||||
if (mp_cmp_d(tmp, 1)) {
|
||||
err = CRYPT_FAIL_TESTVECTOR;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
err = CRYPT_OK;
|
||||
error:
|
||||
done:
|
||||
mp_clear_multi(tmp, g, p, NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the min and max DH key sizes (octets)
|
||||
@param low [out] The smallest key size supported
|
||||
@param high [out] The largest key size supported
|
||||
*/
|
||||
void dh_sizes(int *low, int *high)
|
||||
{
|
||||
int x;
|
||||
LTC_ARGCHKVD(low != NULL);
|
||||
LTC_ARGCHKVD(high != NULL);
|
||||
*low = INT_MAX;
|
||||
*high = 0;
|
||||
for (x = 0; sets[x].size != 0; x++) {
|
||||
if (*low > sets[x].size) *low = sets[x].size;
|
||||
if (*high < sets[x].size) *high = sets[x].size;
|
||||
}
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Returns the key size of a given DH key (octets)
|
||||
Returns the DH group size (octets) for given key
|
||||
@param key The DH key to get the size of
|
||||
@return The size if valid or INT_MAX if not
|
||||
*/
|
||||
int dh_get_size(dh_key *key)
|
||||
@return The group size in octets (0 on error)
|
||||
*/
|
||||
int dh_get_groupsize(dh_key *key)
|
||||
{
|
||||
LTC_ARGCHK(key != NULL);
|
||||
if (dh_is_valid_idx(key->idx) == 1) {
|
||||
return sets[key->idx].size;
|
||||
} else {
|
||||
return INT_MAX; /* large value that would cause dh_make_key() to fail */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Make a DH key [private key pair]
|
||||
@param prng An active PRNG state
|
||||
@param wprng The index for the PRNG you desire to use
|
||||
@param groupsize The size (octets) of used DH group
|
||||
@param key [out] Where the newly created DH key will be stored
|
||||
@return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically.
|
||||
*/
|
||||
int dh_make_key(prng_state *prng, int wprng, int groupsize, dh_key *key)
|
||||
{
|
||||
unsigned char *buf;
|
||||
unsigned long idx, keysize;
|
||||
void *p, *g, *p_minus1;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(key != NULL);
|
||||
LTC_ARGCHK(prng != NULL);
|
||||
|
||||
/* good prng? */
|
||||
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* find group size */
|
||||
for (idx = 0; (groupsize > sets[idx].size) && (sets[idx].size != 0); idx++);
|
||||
if (sets[idx].size == 0) {
|
||||
return CRYPT_INVALID_KEYSIZE;
|
||||
}
|
||||
groupsize = sets[idx].size;
|
||||
|
||||
/* The strength estimates from https://tools.ietf.org/html/rfc3526#section-8
|
||||
* We use "Estimate 2" to get an appropriate private key (exponent) size.
|
||||
*/
|
||||
if (groupsize <= 192) {
|
||||
keysize = 30; /* 1536-bit => key size 240-bit */
|
||||
}
|
||||
else if (groupsize <= 256) {
|
||||
keysize = 40; /* 2048-bit => key size 320-bit */
|
||||
}
|
||||
else if (groupsize <= 384) {
|
||||
keysize = 52; /* 3072-bit => key size 416-bit */
|
||||
}
|
||||
else if (groupsize <= 512) {
|
||||
keysize = 60; /* 4096-bit => key size 480-bit */
|
||||
}
|
||||
else if (groupsize <= 768) {
|
||||
keysize = 67; /* 6144-bit => key size 536-bit */
|
||||
}
|
||||
else if (groupsize <= 1024) {
|
||||
keysize = 77; /* 8192-bit => key size 616-bit */
|
||||
}
|
||||
else {
|
||||
return CRYPT_INVALID_KEYSIZE;
|
||||
}
|
||||
|
||||
/* allocate buffer */
|
||||
buf = XMALLOC(keysize);
|
||||
if (buf == NULL) {
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
|
||||
/* init big numbers */
|
||||
if ((err = mp_init_multi(&g, &p, &p_minus1, &key->x, &key->y, NULL)) != CRYPT_OK) {
|
||||
goto freebuf;
|
||||
}
|
||||
|
||||
if ((err = mp_read_radix(g, sets[idx].base, 16)) != CRYPT_OK) { goto error; }
|
||||
if ((err = mp_read_radix(p, sets[idx].prime, 16)) != CRYPT_OK) { goto error; }
|
||||
if ((err = mp_sub_d(p, 1, p_minus1)) != CRYPT_OK) { goto error; }
|
||||
|
||||
do {
|
||||
/* make up random buf */
|
||||
if (prng_descriptor[wprng].read(buf, keysize, prng) != keysize) {
|
||||
err = CRYPT_ERROR_READPRNG;
|
||||
goto error;
|
||||
}
|
||||
/* load the x value - private key */
|
||||
if ((err = mp_read_unsigned_bin(key->x, buf, keysize)) != CRYPT_OK) { goto error; }
|
||||
/* compute the y value - public key */
|
||||
if ((err = mp_exptmod(g, key->x, p, key->y)) != CRYPT_OK) { goto error; }
|
||||
/* avoid: y <= 1 OR y >= p-1 */
|
||||
} while (mp_cmp(key->y, p_minus1) != LTC_MP_LT || mp_cmp_d(key->y, 1) != LTC_MP_GT);
|
||||
|
||||
/* success */
|
||||
key->idx = idx;
|
||||
key->type = PK_PRIVATE;
|
||||
err = CRYPT_OK;
|
||||
goto done;
|
||||
|
||||
error:
|
||||
mp_clear_multi(key->x, key->y, NULL);
|
||||
done:
|
||||
mp_clear_multi(g, p, p_minus1, NULL);
|
||||
freebuf:
|
||||
zeromem(buf, keysize);
|
||||
XFREE(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
Free the allocated ram for a DH key
|
||||
@param key The key which you wish to free
|
||||
*/
|
||||
void dh_free(dh_key *key)
|
||||
{
|
||||
LTC_ARGCHKVD(key != NULL);
|
||||
if ( key->x ) {
|
||||
mp_clear( key->x );
|
||||
key->x = NULL;
|
||||
}
|
||||
if ( key->y ) {
|
||||
mp_clear( key->y );
|
||||
key->y = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Export a DH key to a binary packet
|
||||
@param out [out] The destination for the key
|
||||
@param outlen [in/out] The max size and resulting size of the DH key
|
||||
@param type Which type of key (PK_PRIVATE or PK_PUBLIC)
|
||||
@param key The key you wish to export
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key)
|
||||
{
|
||||
unsigned long y, z;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
LTC_ARGCHK(key != NULL);
|
||||
|
||||
/* can we store the static header? */
|
||||
if (*outlen < (PACKET_SIZE + 2)) {
|
||||
return CRYPT_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
|
||||
return CRYPT_PK_NOT_PRIVATE;
|
||||
}
|
||||
|
||||
/* header */
|
||||
y = PACKET_SIZE;
|
||||
|
||||
/* header */
|
||||
out[y++] = type;
|
||||
out[y++] = (unsigned char)(sets[key->idx].size / 8);
|
||||
|
||||
/* export y */
|
||||
OUTPUT_BIGNUM(key->y, out, y, z);
|
||||
|
||||
if (type == PK_PRIVATE) {
|
||||
/* export x */
|
||||
OUTPUT_BIGNUM(key->x, out, y, z);
|
||||
}
|
||||
|
||||
/* store header */
|
||||
packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_KEY);
|
||||
|
||||
/* store len */
|
||||
*outlen = y;
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
Import a DH key from a binary packet
|
||||
@param in The packet to read
|
||||
@param inlen The length of the input packet
|
||||
@param key [out] Where to import the key to
|
||||
@return CRYPT_OK if successful, on error all allocated memory is freed automatically
|
||||
*/
|
||||
int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key)
|
||||
{
|
||||
unsigned long x, y, s;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(key != NULL);
|
||||
|
||||
/* make sure valid length */
|
||||
if ((2+PACKET_SIZE) > inlen) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* check type byte */
|
||||
if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_KEY)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* init */
|
||||
if ((err = mp_init_multi(&key->x, &key->y, NULL)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* advance past packet header */
|
||||
y = PACKET_SIZE;
|
||||
|
||||
/* key type, e.g. private, public */
|
||||
key->type = (int)in[y++];
|
||||
|
||||
/* key size in bytes */
|
||||
s = (unsigned long)in[y++] * 8;
|
||||
|
||||
for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size != 0); x++);
|
||||
if (sets[x].size == 0) {
|
||||
err = CRYPT_INVALID_KEYSIZE;
|
||||
goto error;
|
||||
}
|
||||
key->idx = (int)x;
|
||||
|
||||
/* type check both values */
|
||||
if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE)) {
|
||||
err = CRYPT_PK_TYPE_MISMATCH;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* is the key idx valid? */
|
||||
if (dh_is_valid_idx(key->idx) != 1) {
|
||||
err = CRYPT_PK_TYPE_MISMATCH;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* load public value g^x mod p*/
|
||||
INPUT_BIGNUM(key->y, in, x, y, inlen);
|
||||
|
||||
if (key->type == PK_PRIVATE) {
|
||||
INPUT_BIGNUM(key->x, in, x, y, inlen);
|
||||
}
|
||||
|
||||
/* eliminate private key if public */
|
||||
if (key->type == PK_PUBLIC) {
|
||||
mp_clear(key->x);
|
||||
key->x = NULL;
|
||||
}
|
||||
|
||||
return CRYPT_OK;
|
||||
error:
|
||||
mp_clear_multi(key->y, key->x, NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
Create a DH shared secret.
|
||||
@param private_key The private DH key in the pair
|
||||
@param public_key The public DH key in the pair
|
||||
@param out [out] The destination of the shared data
|
||||
@param outlen [in/out] The max size and resulting size of the shared data.
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int dh_shared_secret(dh_key *private_key, dh_key *public_key,
|
||||
unsigned char *out, unsigned long *outlen)
|
||||
{
|
||||
void *tmp, *p, *p_minus1;
|
||||
unsigned long x;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(private_key != NULL);
|
||||
LTC_ARGCHK(public_key != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
|
||||
/* types valid? */
|
||||
if (private_key->type != PK_PRIVATE) {
|
||||
return CRYPT_PK_NOT_PRIVATE;
|
||||
}
|
||||
|
||||
/* same idx? */
|
||||
if (private_key->idx != public_key->idx) {
|
||||
return CRYPT_PK_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
/* compute y^x mod p */
|
||||
if ((err = mp_init_multi(&tmp, &p, &p_minus1, NULL)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((err = mp_read_radix(p, sets[private_key->idx].prime, 16)) != CRYPT_OK) { goto error; }
|
||||
if ((err = mp_sub_d(p, 1, p_minus1)) != CRYPT_OK) { goto error; }
|
||||
if (mp_cmp(public_key->y, p_minus1) != LTC_MP_LT || mp_cmp_d(public_key->y, 1) != LTC_MP_GT) {
|
||||
/* reject public key with: y <= 1 OR y >= p-1 */
|
||||
err = CRYPT_INVALID_ARG;
|
||||
goto error;
|
||||
}
|
||||
if ((err = mp_exptmod(public_key->y, private_key->x, p, tmp)) != CRYPT_OK) { goto error; }
|
||||
|
||||
/* enough space for output? */
|
||||
x = (unsigned long)mp_unsigned_bin_size(tmp);
|
||||
if (*outlen < x) {
|
||||
err = CRYPT_BUFFER_OVERFLOW;
|
||||
goto error;
|
||||
}
|
||||
if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) { goto error; }
|
||||
*outlen = x;
|
||||
err = CRYPT_OK;
|
||||
|
||||
error:
|
||||
mp_clear_multi(p_minus1, p, tmp, NULL);
|
||||
return err;
|
||||
if (key == NULL) return 0;
|
||||
return mp_unsigned_bin_size(key->prime);
|
||||
}
|
||||
|
||||
#endif /* LTC_MDH */
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
|
||||
#include "tomcrypt.h"
|
||||
|
||||
#ifdef LTC_MDH
|
||||
|
||||
/**
|
||||
Check DH public key (INTERNAL ONLY, not part of public API)
|
||||
@param key The key you wish to test
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int dh_check_pubkey(dh_key *key)
|
||||
{
|
||||
void *p_minus1;
|
||||
ltc_mp_digit digit;
|
||||
int i, digit_count, bits_set = 0, err;
|
||||
|
||||
LTC_ARGCHK(key != NULL);
|
||||
LTC_ARGCHK(key->y != NULL);
|
||||
LTC_ARGCHK(key->base != NULL);
|
||||
LTC_ARGCHK(key->prime != NULL);
|
||||
|
||||
if ((err = mp_init(&p_minus1)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* avoid: y <= 1 OR y >= p-1 */
|
||||
if ((err = mp_sub_d(key->prime, 1, p_minus1)) != CRYPT_OK) {
|
||||
goto error;
|
||||
}
|
||||
if (mp_cmp(key->y, p_minus1) != LTC_MP_LT || mp_cmp_d(key->y, 1) != LTC_MP_GT) {
|
||||
err = CRYPT_INVALID_ARG;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* public key must have more than one bit set */
|
||||
digit_count = mp_get_digit_count(key->y);
|
||||
for (i = 0; i < digit_count && bits_set < 2; i++) {
|
||||
digit = mp_get_digit(key->y, i);
|
||||
while (digit > 0) {
|
||||
if (digit & 1) bits_set++;
|
||||
digit >>= 1;
|
||||
}
|
||||
}
|
||||
if (bits_set > 1) {
|
||||
err = CRYPT_OK;
|
||||
}
|
||||
else {
|
||||
err = CRYPT_INVALID_ARG;
|
||||
}
|
||||
|
||||
error:
|
||||
mp_clear(p_minus1);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* LTC_MDH */
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
||||
@@ -0,0 +1,62 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
|
||||
#include "tomcrypt.h"
|
||||
|
||||
#ifdef LTC_MDH
|
||||
|
||||
/**
|
||||
Export a DH key to a binary packet
|
||||
@param out [out] The destination for the key
|
||||
@param outlen [in/out] The max size and resulting size of the DH key
|
||||
@param type Which type of key (PK_PRIVATE or PK_PUBLIC)
|
||||
@param key The key you wish to export
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key)
|
||||
{
|
||||
unsigned char flags[1];
|
||||
int err;
|
||||
unsigned long version = 0;
|
||||
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
LTC_ARGCHK(key != NULL);
|
||||
|
||||
if (type == PK_PRIVATE) {
|
||||
/* export x - private key */
|
||||
flags[0] = 1;
|
||||
err = der_encode_sequence_multi(out, outlen,
|
||||
LTC_ASN1_SHORT_INTEGER, 1UL, &version,
|
||||
LTC_ASN1_BIT_STRING, 1UL, flags,
|
||||
LTC_ASN1_INTEGER, 1UL, key->prime,
|
||||
LTC_ASN1_INTEGER, 1UL, key->base,
|
||||
LTC_ASN1_INTEGER, 1UL, key->x,
|
||||
LTC_ASN1_EOL, 0UL, NULL);
|
||||
}
|
||||
else {
|
||||
/* export y - public key */
|
||||
flags[0] = 0;
|
||||
err = der_encode_sequence_multi(out, outlen,
|
||||
LTC_ASN1_SHORT_INTEGER, 1UL, &version,
|
||||
LTC_ASN1_BIT_STRING, 1UL, flags,
|
||||
LTC_ASN1_INTEGER, 1UL, key->prime,
|
||||
LTC_ASN1_INTEGER, 1UL, key->base,
|
||||
LTC_ASN1_INTEGER, 1UL, key->y,
|
||||
LTC_ASN1_EOL, 0UL, NULL);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* LTC_MDH */
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
||||
@@ -0,0 +1,68 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
|
||||
#include "tomcrypt.h"
|
||||
|
||||
#ifdef LTC_MDH
|
||||
|
||||
static unsigned long _count_digits(int radix, void *num)
|
||||
{
|
||||
void *r, *t;
|
||||
unsigned long digits = 0;
|
||||
|
||||
if (mp_iszero(num) == LTC_MP_YES) return 1;
|
||||
if (mp_init_multi(&t, &r, NULL) != CRYPT_OK) return 0;
|
||||
mp_copy(num, t);
|
||||
mp_set_int(r, radix);
|
||||
while (mp_iszero(t) == LTC_MP_NO) {
|
||||
if (mp_div(t, r, t, NULL) != CRYPT_OK) {
|
||||
mp_clear_multi(t, r, NULL);
|
||||
return 0;
|
||||
}
|
||||
digits++;
|
||||
}
|
||||
mp_clear_multi(t, r, NULL);
|
||||
return digits;
|
||||
}
|
||||
|
||||
/**
|
||||
Export a DH key to a binary packet
|
||||
@param out [out] The destination for the key
|
||||
@param outlen [in/out] The max size and resulting size of the DH key
|
||||
@param type Which type of key (PK_PRIVATE or PK_PUBLIC)
|
||||
@param key The key you wish to export
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int dh_export_radix(int radix, void *out, unsigned long *outlen, int type, dh_key *key)
|
||||
{
|
||||
unsigned long len;
|
||||
void *k;
|
||||
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
LTC_ARGCHK(key != NULL);
|
||||
LTC_ARGCHK((radix >= 2 && radix <= 64) || radix == 256);
|
||||
|
||||
k = (type == PK_PRIVATE) ? key->x : key->y;
|
||||
len = (radix == 256) ? mp_unsigned_bin_size(k) : _count_digits(radix, k) + 1;
|
||||
|
||||
if (*outlen < len) {
|
||||
*outlen = len;
|
||||
return CRYPT_BUFFER_OVERFLOW;
|
||||
}
|
||||
*outlen = len;
|
||||
|
||||
return (radix == 256) ? mp_to_unsigned_bin(k, out) : mp_toradix(k, out, radix);
|
||||
}
|
||||
|
||||
#endif /* LTC_MDH */
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
||||
@@ -0,0 +1,43 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
|
||||
#include "tomcrypt.h"
|
||||
|
||||
#ifdef LTC_MDH
|
||||
|
||||
/**
|
||||
Free the allocated ram for a DH key
|
||||
@param key The key which you wish to free
|
||||
*/
|
||||
void dh_free(dh_key *key)
|
||||
{
|
||||
LTC_ARGCHKVD(key != NULL);
|
||||
if ( key->base ) {
|
||||
mp_clear( key->base );
|
||||
key->base = NULL;
|
||||
}
|
||||
if ( key->prime ) {
|
||||
mp_clear( key->prime );
|
||||
key->prime = NULL;
|
||||
}
|
||||
if ( key->x ) {
|
||||
mp_clear( key->x );
|
||||
key->x = NULL;
|
||||
}
|
||||
if ( key->y ) {
|
||||
mp_clear( key->y );
|
||||
key->y = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* LTC_MDH */
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
||||
@@ -0,0 +1,97 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
|
||||
#include "tomcrypt.h"
|
||||
|
||||
#ifdef LTC_MDH
|
||||
|
||||
/**
|
||||
Import a DH key from a binary packet
|
||||
@param in The packet to read
|
||||
@param inlen The length of the input packet
|
||||
@param key [out] Where to import the key to
|
||||
@return CRYPT_OK if successful, on error all allocated memory is freed automatically
|
||||
*/
|
||||
int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key)
|
||||
{
|
||||
unsigned char flags[1];
|
||||
int err;
|
||||
unsigned long version;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(key != NULL);
|
||||
|
||||
/* init */
|
||||
if ((err = mp_init_multi(&key->prime, &key->base, &key->x, &key->y, NULL)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* find out what type of key it is */
|
||||
err = der_decode_sequence_multi(in, inlen,
|
||||
LTC_ASN1_SHORT_INTEGER, 1UL, &version,
|
||||
LTC_ASN1_BIT_STRING, 1UL, &flags,
|
||||
LTC_ASN1_EOL, 0UL, NULL);
|
||||
if (err != CRYPT_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (version == 0) {
|
||||
if (flags[0] == 1) {
|
||||
key->type = PK_PRIVATE;
|
||||
if ((err = der_decode_sequence_multi(in, inlen,
|
||||
LTC_ASN1_SHORT_INTEGER, 1UL, &version,
|
||||
LTC_ASN1_BIT_STRING, 1UL, flags,
|
||||
LTC_ASN1_INTEGER, 1UL, key->prime,
|
||||
LTC_ASN1_INTEGER, 1UL, key->base,
|
||||
LTC_ASN1_INTEGER, 1UL, key->x,
|
||||
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
|
||||
goto error;
|
||||
}
|
||||
/* compute public key: y = (base ^ x) mod prime */
|
||||
if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
key->type = PK_PUBLIC;
|
||||
if ((err = der_decode_sequence_multi(in, inlen,
|
||||
LTC_ASN1_SHORT_INTEGER, 1UL, &version,
|
||||
LTC_ASN1_BIT_STRING, 1UL, flags,
|
||||
LTC_ASN1_INTEGER, 1UL, key->prime,
|
||||
LTC_ASN1_INTEGER, 1UL, key->base,
|
||||
LTC_ASN1_INTEGER, 1UL, key->y,
|
||||
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
|
||||
goto error;
|
||||
}
|
||||
mp_clear(key->x);
|
||||
key->x = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
err = CRYPT_INVALID_PACKET;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* check public key */
|
||||
if ((err = dh_check_pubkey(key)) != CRYPT_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return CRYPT_OK;
|
||||
|
||||
error:
|
||||
mp_clear_multi(key->prime, key->base, key->y, key->x, NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* LTC_MDH */
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
||||
@@ -0,0 +1,90 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
|
||||
#include "tomcrypt.h"
|
||||
|
||||
#ifdef LTC_MDH
|
||||
|
||||
/**
|
||||
Import a DH key from a binary string
|
||||
@param in The string to read
|
||||
@param inlen The length of the input packet
|
||||
@param type The type of key (PK_PRIVATE or PK_PUBLIC)
|
||||
@param base The base (generator) in hex string
|
||||
@param prime The prime in hex string
|
||||
@param key [out] Where to import the key to
|
||||
@return CRYPT_OK if successful, on error all allocated memory is freed automatically
|
||||
*/
|
||||
int dh_import_radix(int radix,
|
||||
void *in, unsigned long inlen,
|
||||
void *prime, unsigned long primelen,
|
||||
void *base, unsigned long baselen,
|
||||
int type, dh_key *key)
|
||||
{
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(base != NULL);
|
||||
LTC_ARGCHK(prime != NULL);
|
||||
LTC_ARGCHK(key != NULL);
|
||||
|
||||
if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) {
|
||||
goto error;
|
||||
}
|
||||
if (radix == 256) {
|
||||
if ((err = mp_read_unsigned_bin(key->base, base, baselen)) != CRYPT_OK) { goto error; }
|
||||
if ((err = mp_read_unsigned_bin(key->prime, prime, primelen)) != CRYPT_OK) { goto error; }
|
||||
}
|
||||
else {
|
||||
if ((err = mp_read_radix(key->base, base, radix)) != CRYPT_OK) { goto error; }
|
||||
if ((err = mp_read_radix(key->prime, prime, radix)) != CRYPT_OK) { goto error; }
|
||||
}
|
||||
|
||||
if (type == PK_PRIVATE) {
|
||||
/* load the x value */
|
||||
if (radix == 256) {
|
||||
if ((err = mp_read_unsigned_bin(key->x, in, inlen)) != CRYPT_OK) { goto error; }
|
||||
}
|
||||
else {
|
||||
if ((err = mp_read_radix(key->x, in, radix)) != CRYPT_OK) { goto error; }
|
||||
}
|
||||
/* compute y value */
|
||||
if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) { goto error; }
|
||||
key->type = PK_PRIVATE;
|
||||
}
|
||||
else {
|
||||
/* load the y value */
|
||||
if (radix == 256) {
|
||||
if ((err = mp_read_unsigned_bin(key->y, in, inlen)) != CRYPT_OK) { goto error; }
|
||||
}
|
||||
else {
|
||||
if ((err = mp_read_radix(key->y, in, radix)) != CRYPT_OK) { goto error; }
|
||||
}
|
||||
key->type = PK_PUBLIC;
|
||||
mp_clear(key->x);
|
||||
key->x = NULL;
|
||||
}
|
||||
|
||||
/* check public key */
|
||||
if ((err = dh_check_pubkey(key)) != CRYPT_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return CRYPT_OK;
|
||||
|
||||
error:
|
||||
mp_clear_multi(key->prime, key->base, key->y, key->x, NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* LTC_MDH */
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
||||
@@ -0,0 +1,207 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
|
||||
#include "tomcrypt.h"
|
||||
|
||||
#ifdef LTC_MDH
|
||||
|
||||
static int _dh_groupsize_to_keysize(int groupsize)
|
||||
{
|
||||
/* The strength estimates from https://tools.ietf.org/html/rfc3526#section-8
|
||||
* We use "Estimate 2" to get an appropriate private key (exponent) size.
|
||||
*/
|
||||
if (groupsize <= 0) {
|
||||
return 0;
|
||||
}
|
||||
else if (groupsize <= 192) {
|
||||
return 30; /* 1536-bit => key size 240-bit */
|
||||
}
|
||||
else if (groupsize <= 256) {
|
||||
return 40; /* 2048-bit => key size 320-bit */
|
||||
}
|
||||
else if (groupsize <= 384) {
|
||||
return 52; /* 3072-bit => key size 416-bit */
|
||||
}
|
||||
else if (groupsize <= 512) {
|
||||
return 60; /* 4096-bit => key size 480-bit */
|
||||
}
|
||||
else if (groupsize <= 768) {
|
||||
return 67; /* 6144-bit => key size 536-bit */
|
||||
}
|
||||
else if (groupsize <= 1024) {
|
||||
return 77; /* 8192-bit => key size 616-bit */
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int _dh_make_key(prng_state *prng, int wprng, void *prime, void *base, dh_key *key)
|
||||
{
|
||||
unsigned char *buf;
|
||||
unsigned long keysize;
|
||||
int err, max_iterations = PK_MAX_RETRIES;
|
||||
|
||||
LTC_ARGCHK(key != NULL);
|
||||
LTC_ARGCHK(prng != NULL);
|
||||
LTC_ARGCHK(prime != NULL);
|
||||
LTC_ARGCHK(base != NULL);
|
||||
|
||||
/* good prng? */
|
||||
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* init big numbers */
|
||||
if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* load the prime and the base */
|
||||
if ((err = mp_copy(base, key->base)) != CRYPT_OK) { goto freemp; }
|
||||
if ((err = mp_copy(prime, key->prime)) != CRYPT_OK) { goto freemp; }
|
||||
|
||||
keysize = _dh_groupsize_to_keysize(mp_unsigned_bin_size(key->prime));
|
||||
if (keysize == 0) {
|
||||
err = CRYPT_INVALID_KEYSIZE;
|
||||
goto freemp;
|
||||
}
|
||||
|
||||
/* allocate buffer */
|
||||
buf = XMALLOC(keysize);
|
||||
if (buf == NULL) {
|
||||
err = CRYPT_MEM;
|
||||
goto freemp;
|
||||
}
|
||||
|
||||
key->type = PK_PRIVATE;
|
||||
do {
|
||||
/* make up random buf */
|
||||
if (prng_descriptor[wprng].read(buf, keysize, prng) != keysize) {
|
||||
err = CRYPT_ERROR_READPRNG;
|
||||
goto freebuf;
|
||||
}
|
||||
/* load the x value - private key */
|
||||
if ((err = mp_read_unsigned_bin(key->x, buf, keysize)) != CRYPT_OK) {
|
||||
goto freebuf;
|
||||
}
|
||||
/* compute the y value - public key */
|
||||
if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK) {
|
||||
goto freebuf;
|
||||
}
|
||||
err = dh_check_pubkey(key);
|
||||
} while (err != CRYPT_OK && max_iterations-- > 0);
|
||||
|
||||
freebuf:
|
||||
zeromem(buf, keysize);
|
||||
XFREE(buf);
|
||||
freemp:
|
||||
if (err != CRYPT_OK) mp_clear_multi(key->x, key->y, key->base, key->prime, NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
Make a DH key (custom DH group) [private key pair]
|
||||
@param prng An active PRNG state
|
||||
@param wprng The index for the PRNG you desire to use
|
||||
@param prime_hex The prime p (hexadecimal string)
|
||||
@param base_hex The base g (hexadecimal string)
|
||||
@param key [out] Where the newly created DH key will be stored
|
||||
@return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically.
|
||||
*/
|
||||
static int _dh_make_key_ex(prng_state *prng, int wprng, int radix,
|
||||
void *prime, unsigned long primelen,
|
||||
void *base, unsigned long baselen,
|
||||
dh_key *key)
|
||||
{
|
||||
void *p, *b;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(prime != NULL);
|
||||
LTC_ARGCHK(base != NULL);
|
||||
LTC_ARGCHK((radix >= 2 && radix <= 64) || radix == 256);
|
||||
|
||||
if ((err = mp_init_multi(&p, &b, NULL)) != CRYPT_OK) { return err; }
|
||||
if (radix == 256) {
|
||||
if ((err = mp_read_unsigned_bin(b, base, baselen)) != CRYPT_OK) { goto error; }
|
||||
if ((err = mp_read_unsigned_bin(p, prime, primelen)) != CRYPT_OK) { goto error; }
|
||||
}
|
||||
else {
|
||||
if ((err = mp_read_radix(b, base, radix)) != CRYPT_OK) { goto error; }
|
||||
if ((err = mp_read_radix(p, prime, radix)) != CRYPT_OK) { goto error; }
|
||||
}
|
||||
err = _dh_make_key(prng, wprng, p, b, key);
|
||||
|
||||
error:
|
||||
mp_clear_multi(p, b, NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
Make a DH key (use built-in DH groups) [private key pair]
|
||||
@param prng An active PRNG state
|
||||
@param wprng The index for the PRNG you desire to use
|
||||
@param groupsize The size (octets) of used DH group
|
||||
@param key [out] Where the newly created DH key will be stored
|
||||
@return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically.
|
||||
*/
|
||||
int dh_make_key(prng_state *prng, int wprng, int groupsize, dh_key *key)
|
||||
{
|
||||
int i;
|
||||
|
||||
LTC_ARGCHK(groupsize > 0);
|
||||
|
||||
for (i = 0; (groupsize > ltc_dh_sets[i].size) && (ltc_dh_sets[i].size != 0); i++);
|
||||
if (ltc_dh_sets[i].size == 0) return CRYPT_INVALID_KEYSIZE;
|
||||
|
||||
return _dh_make_key_ex(prng, wprng, 16,
|
||||
ltc_dh_sets[i].prime, strlen(ltc_dh_sets[i].prime) + 1,
|
||||
ltc_dh_sets[i].base, strlen(ltc_dh_sets[i].base) + 1,
|
||||
key);
|
||||
}
|
||||
|
||||
/**
|
||||
Make a DH key (dhparam data: openssl dhparam -outform DER -out dhparam.der 2048)
|
||||
@param prng An active PRNG state
|
||||
@param wprng The index for the PRNG you desire to use
|
||||
@param dhparam The DH param DER encoded data
|
||||
@param dhparamlen The length of dhparam data
|
||||
@param key [out] Where the newly created DH key will be stored
|
||||
@return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically.
|
||||
*/
|
||||
int dh_make_key_dhparam(prng_state *prng, int wprng, unsigned char *dhparam, unsigned long dhparamlen, dh_key *key)
|
||||
{
|
||||
void *prime, *base;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(dhparam != NULL);
|
||||
LTC_ARGCHK(dhparamlen > 0);
|
||||
|
||||
if ((err = mp_init_multi(&prime, &base, NULL)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
if ((err = der_decode_sequence_multi(dhparam, dhparamlen,
|
||||
LTC_ASN1_INTEGER, 1UL, prime,
|
||||
LTC_ASN1_INTEGER, 1UL, base,
|
||||
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
|
||||
goto error;
|
||||
}
|
||||
err = _dh_make_key(prng, wprng, prime, base, key);
|
||||
|
||||
error:
|
||||
mp_clear_multi(prime, base, NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
#endif /* LTC_MDH */
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
||||
@@ -0,0 +1,80 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
|
||||
#include "tomcrypt.h"
|
||||
|
||||
#ifdef LTC_MDH
|
||||
|
||||
/**
|
||||
Create a DH shared secret.
|
||||
@param private_key The private DH key in the pair
|
||||
@param public_key The public DH key in the pair
|
||||
@param out [out] The destination of the shared data
|
||||
@param outlen [in/out] The max size and resulting size of the shared data.
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int dh_shared_secret(dh_key *private_key, dh_key *public_key,
|
||||
unsigned char *out, unsigned long *outlen)
|
||||
{
|
||||
void *tmp;
|
||||
unsigned long x;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(private_key != NULL);
|
||||
LTC_ARGCHK(public_key != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
|
||||
/* types valid? */
|
||||
if (private_key->type != PK_PRIVATE) {
|
||||
return CRYPT_PK_NOT_PRIVATE;
|
||||
}
|
||||
|
||||
/* same DH group? */
|
||||
if (mp_cmp(private_key->prime, public_key->prime) != LTC_MP_EQ) { return CRYPT_PK_TYPE_MISMATCH; }
|
||||
if (mp_cmp(private_key->base, public_key->base) != LTC_MP_EQ) { return CRYPT_PK_TYPE_MISMATCH; }
|
||||
|
||||
/* init big numbers */
|
||||
if ((err = mp_init(&tmp)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* check public key */
|
||||
if ((err = dh_check_pubkey(public_key)) != CRYPT_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* compute tmp = y^x mod p */
|
||||
if ((err = mp_exptmod(public_key->y, private_key->x, private_key->prime, tmp)) != CRYPT_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* enough space for output? */
|
||||
x = (unsigned long)mp_unsigned_bin_size(tmp);
|
||||
if (*outlen < x) {
|
||||
*outlen = x;
|
||||
err = CRYPT_BUFFER_OVERFLOW;
|
||||
goto error;
|
||||
}
|
||||
if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) {
|
||||
goto error;
|
||||
}
|
||||
*outlen = x;
|
||||
err = CRYPT_OK;
|
||||
|
||||
error:
|
||||
mp_clear(tmp);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* LTC_MDH */
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
||||
@@ -1,243 +0,0 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
|
||||
*/
|
||||
#include "tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file dh_static.c
|
||||
DH crypto, Tom St Denis
|
||||
*/
|
||||
|
||||
#ifdef LTC_MDH
|
||||
|
||||
#define __DECL_DH_STATIC_H__
|
||||
#include "dh_static.h"
|
||||
|
||||
/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */
|
||||
const dh_set sets[] = {
|
||||
#ifdef LTC_DH768
|
||||
{ /* 768-bit MODP Group 1 - https://tools.ietf.org/html/rfc7296#appendix-B.1 */
|
||||
96,
|
||||
"DH-768",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
#ifdef LTC_DH1024
|
||||
{ /* 1024-bit MODP Group 2 - https://tools.ietf.org/html/rfc7296#appendix-B.2 */
|
||||
128,
|
||||
"DH-1024",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
|
||||
"FFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
#ifdef LTC_DH1536
|
||||
{ /* 1536-bit MODP Group 5 - https://tools.ietf.org/html/rfc3526#section-2 */
|
||||
192,
|
||||
"DH-1536",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
"670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
#ifdef LTC_DH2048
|
||||
{ /* 2048-bit MODP Group 14 - https://tools.ietf.org/html/rfc3526#section-3 */
|
||||
256,
|
||||
"DH-2048",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
|
||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
|
||||
"15728E5A8AACAA68FFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
#ifdef LTC_DH3072
|
||||
{ /* 3072-bit MODP Group 15 - https://tools.ietf.org/html/rfc3526#section-4 */
|
||||
384,
|
||||
"DH-3072",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
|
||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
|
||||
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
|
||||
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
|
||||
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
|
||||
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
|
||||
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
|
||||
"43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
#ifdef LTC_DH4096
|
||||
{ /* 4096-bit MODP Group 16 - https://tools.ietf.org/html/rfc3526#section-5 */
|
||||
512,
|
||||
"DH-4096",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
|
||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
|
||||
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
|
||||
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
|
||||
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
|
||||
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
|
||||
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
|
||||
"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
|
||||
"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
|
||||
"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
|
||||
"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
|
||||
"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
|
||||
"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
|
||||
"FFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
#ifdef LTC_DH6144
|
||||
{ /* 6144-bit MODP Group 17 - https://tools.ietf.org/html/rfc3526#section-6 */
|
||||
786,
|
||||
"DH-6144",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
|
||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
|
||||
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
|
||||
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
|
||||
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
|
||||
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
|
||||
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
|
||||
"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
|
||||
"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
|
||||
"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
|
||||
"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
|
||||
"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
|
||||
"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
|
||||
"36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
|
||||
"F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
|
||||
"179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
|
||||
"DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
|
||||
"5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
|
||||
"D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
|
||||
"23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
|
||||
"CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
|
||||
"06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
|
||||
"DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
|
||||
"12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
#ifdef LTC_DH8192
|
||||
{ /* 8192-bit MODP Group 18 - https://tools.ietf.org/html/rfc3526#section-7 */
|
||||
1024,
|
||||
"DH-8192",
|
||||
"2",
|
||||
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
|
||||
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
|
||||
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
|
||||
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
|
||||
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
|
||||
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
|
||||
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
|
||||
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
|
||||
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
|
||||
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
|
||||
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
|
||||
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
|
||||
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
|
||||
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
|
||||
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
|
||||
"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
|
||||
"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
|
||||
"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
|
||||
"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
|
||||
"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
|
||||
"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
|
||||
"36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
|
||||
"F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
|
||||
"179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
|
||||
"DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
|
||||
"5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
|
||||
"D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
|
||||
"23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
|
||||
"CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
|
||||
"06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
|
||||
"DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
|
||||
"12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4"
|
||||
"38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300"
|
||||
"741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568"
|
||||
"3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
|
||||
"22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B"
|
||||
"4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A"
|
||||
"062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36"
|
||||
"4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1"
|
||||
"B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92"
|
||||
"4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47"
|
||||
"9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71"
|
||||
"60C980DD98EDD3DFFFFFFFFFFFFFFFFF"
|
||||
},
|
||||
#endif
|
||||
{
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
int dh_is_valid_idx(int n)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = 0; sets[x].size; x++);
|
||||
if ((n < 0) || (n >= x)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#endif /* LTC_MDH */
|
||||
@@ -1,125 +0,0 @@
|
||||
#ifndef __DH_STATIC_H__
|
||||
#define __DH_STATIC_H__
|
||||
#ifndef __DECL_DH_STATIC_H__
|
||||
#define __DECL_DH_STATIC_H__ extern
|
||||
#endif
|
||||
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
|
||||
*/
|
||||
#include "tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file dh_static.h
|
||||
DH crypto, Tom St Denis
|
||||
*/
|
||||
|
||||
#ifdef LTC_MDH
|
||||
|
||||
/* size of a packet header in bytes */
|
||||
#define PACKET_SIZE 4
|
||||
|
||||
/* Section tags */
|
||||
#define PACKET_SECT_DH 1
|
||||
|
||||
/* Subsection Tags for the first three sections */
|
||||
#define PACKET_SUB_KEY 0
|
||||
#define PACKET_SUB_ENCRYPTED 1
|
||||
#define PACKET_SUB_SIGNED 2
|
||||
#define PACKET_SUB_ENC_KEY 3
|
||||
|
||||
#define OUTPUT_BIGNUM(num, out, y, z) \
|
||||
{ \
|
||||
if ((y + 4) > *outlen) { return CRYPT_BUFFER_OVERFLOW; } \
|
||||
z = (unsigned long)mp_unsigned_bin_size(num); \
|
||||
STORE32L(z, out+y); \
|
||||
y += 4; \
|
||||
if ((y + z) > *outlen) { return CRYPT_BUFFER_OVERFLOW; } \
|
||||
if ((err = mp_to_unsigned_bin(num, out+y)) != CRYPT_OK) { return err; } \
|
||||
y += z; \
|
||||
}
|
||||
|
||||
#define INPUT_BIGNUM(num, in, x, y, inlen) \
|
||||
{ \
|
||||
/* load value */ \
|
||||
if ((y + 4) > inlen) { \
|
||||
err = CRYPT_INVALID_PACKET; \
|
||||
goto error; \
|
||||
} \
|
||||
LOAD32L(x, in+y); \
|
||||
y += 4; \
|
||||
\
|
||||
/* sanity check... */ \
|
||||
if ((x+y) > inlen) { \
|
||||
err = CRYPT_INVALID_PACKET; \
|
||||
goto error; \
|
||||
} \
|
||||
\
|
||||
/* load it */ \
|
||||
if ((err = mp_read_unsigned_bin(num, (unsigned char *)in+y, (int)x)) != CRYPT_OK) {\
|
||||
goto error; \
|
||||
} \
|
||||
y += x; \
|
||||
}
|
||||
|
||||
static LTC_INLINE void packet_store_header (unsigned char *dst, int section, int subsection)
|
||||
{
|
||||
LTC_ARGCHKVD(dst != NULL);
|
||||
|
||||
/* store version number */
|
||||
dst[0] = (unsigned char)(CRYPT&255);
|
||||
dst[1] = (unsigned char)((CRYPT>>8)&255);
|
||||
|
||||
/* store section and subsection */
|
||||
dst[2] = (unsigned char)(section & 255);
|
||||
dst[3] = (unsigned char)(subsection & 255);
|
||||
|
||||
}
|
||||
|
||||
static LTC_INLINE int packet_valid_header (unsigned char *src, int section, int subsection)
|
||||
{
|
||||
unsigned long ver;
|
||||
|
||||
LTC_ARGCHK(src != NULL);
|
||||
|
||||
/* check version */
|
||||
ver = ((unsigned long)src[0]) | ((unsigned long)src[1] << 8U);
|
||||
if (CRYPT < ver) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* check section and subsection */
|
||||
if (section != (int)src[2] || subsection != (int)src[3]) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#ifndef DH_BUF_SIZE
|
||||
/* max export size we'll encounter (smaller than this but lets round up a bit) */
|
||||
#define DH_BUF_SIZE 1200
|
||||
#endif /* DH_BUF_SIZE */
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
char *name, *base, *prime;
|
||||
} dh_set;
|
||||
|
||||
/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */
|
||||
__DECL_DH_STATIC_H__ const dh_set sets[];
|
||||
|
||||
|
||||
int dh_is_valid_idx(int n);
|
||||
|
||||
|
||||
#endif /* __DH_STATIC_H__ */
|
||||
|
||||
#endif /* LTC_MDH */
|
||||
@@ -1,490 +0,0 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*
|
||||
* Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
|
||||
*/
|
||||
|
||||
#include "tomcrypt.h"
|
||||
|
||||
#ifdef LTC_MDH
|
||||
/**
|
||||
@file dh_sys.c
|
||||
DH Crypto, Tom St Denis
|
||||
*/
|
||||
|
||||
#include "dh_static.h"
|
||||
|
||||
|
||||
/**
|
||||
Encrypt a short symmetric key with a public DH key
|
||||
@param in The symmetric key to encrypt
|
||||
@param inlen The length of the key (octets)
|
||||
@param out [out] The ciphertext
|
||||
@param outlen [in/out] The max size and resulting size of the ciphertext
|
||||
@param prng An active PRNG state
|
||||
@param wprng The index of the PRNG desired
|
||||
@param hash The index of the hash desired (must produce a digest of size >= the size of the plaintext)
|
||||
@param key The public key you wish to encrypt with.
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int dh_encrypt_key(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
prng_state *prng, int wprng, int hash,
|
||||
dh_key *key)
|
||||
{
|
||||
unsigned char *pub_expt, *dh_shared, *skey;
|
||||
dh_key pubkey;
|
||||
unsigned long x, y, z, pubkeysize;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
LTC_ARGCHK(key != NULL);
|
||||
|
||||
/* check that wprng/hash are not invalid */
|
||||
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((err = hash_is_valid(hash)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (inlen > hash_descriptor[hash].hashsize) {
|
||||
return CRYPT_INVALID_HASH;
|
||||
}
|
||||
|
||||
/* allocate memory */
|
||||
pub_expt = XMALLOC(DH_BUF_SIZE);
|
||||
dh_shared = XMALLOC(DH_BUF_SIZE);
|
||||
skey = XMALLOC(MAXBLOCKSIZE);
|
||||
if (pub_expt == NULL || dh_shared == NULL || skey == NULL) {
|
||||
if (pub_expt != NULL) {
|
||||
XFREE(pub_expt);
|
||||
}
|
||||
if (dh_shared != NULL) {
|
||||
XFREE(dh_shared);
|
||||
}
|
||||
if (skey != NULL) {
|
||||
XFREE(skey);
|
||||
}
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
|
||||
/* make a random key and export the public copy */
|
||||
if ((err = dh_make_key(prng, wprng, dh_get_size(key), &pubkey)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
pubkeysize = DH_BUF_SIZE;
|
||||
if ((err = dh_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
|
||||
dh_free(&pubkey);
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
/* now check if the out buffer is big enough */
|
||||
if (*outlen < (1 + 4 + 4 + PACKET_SIZE + pubkeysize + inlen)) {
|
||||
dh_free(&pubkey);
|
||||
err = CRYPT_BUFFER_OVERFLOW;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
x = DH_BUF_SIZE;
|
||||
if ((err = dh_shared_secret(&pubkey, key, dh_shared, &x)) != CRYPT_OK) {
|
||||
dh_free(&pubkey);
|
||||
goto LBL_ERR;
|
||||
}
|
||||
dh_free(&pubkey);
|
||||
|
||||
z = MAXBLOCKSIZE;
|
||||
if ((err = hash_memory(hash, dh_shared, x, skey, &z)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
/* store header */
|
||||
packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_ENC_KEY);
|
||||
|
||||
/* output header */
|
||||
y = PACKET_SIZE;
|
||||
|
||||
/* size of hash name and the name itself */
|
||||
out[y++] = hash_descriptor[hash].ID;
|
||||
|
||||
/* length of DH pubkey and the key itself */
|
||||
STORE32L(pubkeysize, out+y);
|
||||
y += 4;
|
||||
for (x = 0; x < pubkeysize; x++, y++) {
|
||||
out[y] = pub_expt[x];
|
||||
}
|
||||
|
||||
/* Store the encrypted key */
|
||||
STORE32L(inlen, out+y);
|
||||
y += 4;
|
||||
|
||||
for (x = 0; x < inlen; x++, y++) {
|
||||
out[y] = skey[x] ^ in[x];
|
||||
}
|
||||
*outlen = y;
|
||||
|
||||
err = CRYPT_OK;
|
||||
LBL_ERR:
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
/* clean up */
|
||||
zeromem(pub_expt, DH_BUF_SIZE);
|
||||
zeromem(dh_shared, DH_BUF_SIZE);
|
||||
zeromem(skey, MAXBLOCKSIZE);
|
||||
#endif
|
||||
XFREE(skey);
|
||||
XFREE(dh_shared);
|
||||
XFREE(pub_expt);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
Decrypt a DH encrypted symmetric key
|
||||
@param in The DH encrypted packet
|
||||
@param inlen The length of the DH encrypted packet
|
||||
@param out The plaintext
|
||||
@param outlen [in/out] The max size and resulting size of the plaintext
|
||||
@param key The private DH key corresponding to the public key that encrypted the plaintext
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int dh_decrypt_key(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
dh_key *key)
|
||||
{
|
||||
unsigned char *shared_secret, *skey;
|
||||
unsigned long x, y, z, keysize;
|
||||
int hash, err;
|
||||
dh_key pubkey;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
LTC_ARGCHK(key != NULL);
|
||||
|
||||
/* right key type? */
|
||||
if (key->type != PK_PRIVATE) {
|
||||
return CRYPT_PK_NOT_PRIVATE;
|
||||
}
|
||||
|
||||
/* allocate ram */
|
||||
shared_secret = XMALLOC(DH_BUF_SIZE);
|
||||
skey = XMALLOC(MAXBLOCKSIZE);
|
||||
if (shared_secret == NULL || skey == NULL) {
|
||||
if (shared_secret != NULL) {
|
||||
XFREE(shared_secret);
|
||||
}
|
||||
if (skey != NULL) {
|
||||
XFREE(skey);
|
||||
}
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
|
||||
/* check if initial header should fit */
|
||||
if (inlen < PACKET_SIZE+1+4+4) {
|
||||
err = CRYPT_INVALID_PACKET;
|
||||
goto LBL_ERR;
|
||||
} else {
|
||||
inlen -= PACKET_SIZE+1+4+4;
|
||||
}
|
||||
|
||||
/* is header correct? */
|
||||
if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
/* now lets get the hash name */
|
||||
y = PACKET_SIZE;
|
||||
hash = find_hash_id(in[y++]);
|
||||
if (hash == -1) {
|
||||
err = CRYPT_INVALID_HASH;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
/* get public key */
|
||||
LOAD32L(x, in+y);
|
||||
|
||||
/* now check if the imported key will fit */
|
||||
if (inlen < x) {
|
||||
err = CRYPT_INVALID_PACKET;
|
||||
goto LBL_ERR;
|
||||
} else {
|
||||
inlen -= x;
|
||||
}
|
||||
|
||||
y += 4;
|
||||
if ((err = dh_import(in+y, x, &pubkey)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
y += x;
|
||||
|
||||
/* make shared key */
|
||||
x = DH_BUF_SIZE;
|
||||
if ((err = dh_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) {
|
||||
dh_free(&pubkey);
|
||||
goto LBL_ERR;
|
||||
}
|
||||
dh_free(&pubkey);
|
||||
|
||||
z = MAXBLOCKSIZE;
|
||||
if ((err = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
/* load in the encrypted key */
|
||||
LOAD32L(keysize, in+y);
|
||||
|
||||
/* will the out fit as part of the input */
|
||||
if (inlen < keysize) {
|
||||
err = CRYPT_INVALID_PACKET;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
if (keysize > *outlen) {
|
||||
err = CRYPT_BUFFER_OVERFLOW;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
y += 4;
|
||||
|
||||
*outlen = keysize;
|
||||
|
||||
for (x = 0; x < keysize; x++, y++) {
|
||||
out[x] = skey[x] ^ in[y];
|
||||
}
|
||||
|
||||
err = CRYPT_OK;
|
||||
LBL_ERR:
|
||||
#ifdef LTC_CLEAN_STACK
|
||||
zeromem(shared_secret, DH_BUF_SIZE);
|
||||
zeromem(skey, MAXBLOCKSIZE);
|
||||
#endif
|
||||
|
||||
XFREE(skey);
|
||||
XFREE(shared_secret);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* perform an ElGamal Signature of a hash
|
||||
*
|
||||
* The math works as follows. x is the private key, M is the message to sign
|
||||
|
||||
1. pick a random k
|
||||
2. compute a = g^k mod p
|
||||
3. compute b = (M - xa)/k mod p
|
||||
4. Send (a,b)
|
||||
|
||||
Now to verify with y=g^x mod p, a and b
|
||||
|
||||
1. compute y^a * a^b = g^(xa) * g^(k*(M-xa)/k)
|
||||
= g^(xa + (M - xa))
|
||||
= g^M [all mod p]
|
||||
|
||||
2. Compare against g^M mod p [based on input hash].
|
||||
3. If result of #2 == result of #1 then signature valid
|
||||
*/
|
||||
|
||||
/**
|
||||
Sign a message digest using a DH private key
|
||||
@param in The data to sign
|
||||
@param inlen The length of the input (octets)
|
||||
@param out [out] The destination of the signature
|
||||
@param outlen [in/out] The max size and resulting size of the output
|
||||
@param prng An active PRNG state
|
||||
@param wprng The index of the PRNG desired
|
||||
@param key A private DH key
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int dh_sign_hash(const unsigned char *in, unsigned long inlen,
|
||||
unsigned char *out, unsigned long *outlen,
|
||||
prng_state *prng, int wprng, dh_key *key)
|
||||
{
|
||||
void *a, *b, *k, *m, *g, *p, *p1, *tmp;
|
||||
unsigned char *buf;
|
||||
unsigned long x, y;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
LTC_ARGCHK(key != NULL);
|
||||
|
||||
/* check parameters */
|
||||
if (key->type != PK_PRIVATE) {
|
||||
return CRYPT_PK_NOT_PRIVATE;
|
||||
}
|
||||
|
||||
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* is the IDX valid ? */
|
||||
if (dh_is_valid_idx(key->idx) != 1) {
|
||||
return CRYPT_PK_INVALID_TYPE;
|
||||
}
|
||||
|
||||
/* allocate ram for buf */
|
||||
buf = XMALLOC(520);
|
||||
|
||||
/* make up a random value k,
|
||||
* since the order of the group is prime
|
||||
* we need not check if gcd(k, r) is 1
|
||||
*/
|
||||
if (prng_descriptor[wprng].read(buf, sets[key->idx].size, prng) !=
|
||||
(unsigned long)(sets[key->idx].size)) {
|
||||
err = CRYPT_ERROR_READPRNG;
|
||||
goto LBL_ERR_1;
|
||||
}
|
||||
|
||||
/* init bignums */
|
||||
if ((err = mp_init_multi(&a, &b, &k, &m, &p, &g, &p1, &tmp, NULL)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
/* load k and m */
|
||||
if ((err = mp_read_unsigned_bin(m, (unsigned char *)in, inlen)) != CRYPT_OK) { goto LBL_ERR; }
|
||||
if ((err = mp_read_unsigned_bin(k, buf, sets[key->idx].size)) != CRYPT_OK) { goto LBL_ERR; }
|
||||
|
||||
/* load g, p and p1 */
|
||||
if ((err = mp_read_radix(g, sets[key->idx].base, 16)) != CRYPT_OK) { goto LBL_ERR; }
|
||||
if ((err = mp_read_radix(p, sets[key->idx].prime, 16)) != CRYPT_OK) { goto LBL_ERR; }
|
||||
if ((err = mp_sub_d(p, 1, p1)) != CRYPT_OK) { goto LBL_ERR; }
|
||||
if ((err = mp_div_2(p1, p1)) != CRYPT_OK) { goto LBL_ERR; } /* p1 = (p-1)/2 */
|
||||
|
||||
/* now get a = g^k mod p */
|
||||
if ((err = mp_exptmod(g, k, p, a)) != CRYPT_OK) { goto LBL_ERR; }
|
||||
|
||||
/* now find M = xa + kb mod p1 or just b = (M - xa)/k mod p1 */
|
||||
if ((err = mp_invmod(k, p1, k)) != CRYPT_OK) { goto LBL_ERR; } /* k = 1/k mod p1 */
|
||||
if ((err = mp_mulmod(a, key->x, p1, tmp)) != CRYPT_OK) { goto LBL_ERR; } /* tmp = xa */
|
||||
if ((err = mp_submod(m, tmp, p1, tmp)) != CRYPT_OK) { goto LBL_ERR; } /* tmp = M - xa */
|
||||
if ((err = mp_mulmod(k, tmp, p1, b)) != CRYPT_OK) { goto LBL_ERR; } /* b = (M - xa)/k */
|
||||
|
||||
/* check for overflow */
|
||||
if ((unsigned long)(PACKET_SIZE + 4 + 4 + mp_unsigned_bin_size(a) + mp_unsigned_bin_size(b)) > *outlen) {
|
||||
err = CRYPT_BUFFER_OVERFLOW;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
/* store header */
|
||||
y = PACKET_SIZE;
|
||||
|
||||
/* now store them both (a,b) */
|
||||
x = (unsigned long)mp_unsigned_bin_size(a);
|
||||
STORE32L(x, out+y); y += 4;
|
||||
if ((err = mp_to_unsigned_bin(a, out+y)) != CRYPT_OK) { goto LBL_ERR; }
|
||||
y += x;
|
||||
|
||||
x = (unsigned long)mp_unsigned_bin_size(b);
|
||||
STORE32L(x, out+y); y += 4;
|
||||
if ((err = mp_to_unsigned_bin(b, out+y)) != CRYPT_OK) { goto LBL_ERR; }
|
||||
y += x;
|
||||
|
||||
/* check if size too big */
|
||||
if (*outlen < y) {
|
||||
err = CRYPT_BUFFER_OVERFLOW;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
/* store header */
|
||||
packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_SIGNED);
|
||||
*outlen = y;
|
||||
|
||||
err = CRYPT_OK;
|
||||
LBL_ERR:
|
||||
mp_clear_multi(tmp, p1, g, p, m, k, b, a, NULL);
|
||||
LBL_ERR_1:
|
||||
|
||||
XFREE(buf);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Verify the signature given
|
||||
@param sig The signature
|
||||
@param siglen The length of the signature (octets)
|
||||
@param hash The hash that was signed
|
||||
@param hashlen The length of the hash (octets)
|
||||
@param stat [out] Result of signature comparison, 1==valid, 0==invalid
|
||||
@param key The public DH key that signed the hash
|
||||
@return CRYPT_OK if succsessful (even if signature is invalid)
|
||||
*/
|
||||
int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
|
||||
const unsigned char *hash, unsigned long hashlen,
|
||||
int *stat, dh_key *key)
|
||||
{
|
||||
void *a, *b, *p, *g, *m, *tmp;
|
||||
unsigned long x, y;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(sig != NULL);
|
||||
LTC_ARGCHK(hash != NULL);
|
||||
LTC_ARGCHK(stat != NULL);
|
||||
LTC_ARGCHK(key != NULL);
|
||||
|
||||
/* default to invalid */
|
||||
*stat = 0;
|
||||
|
||||
/* check initial input length */
|
||||
if (siglen < PACKET_SIZE+4+4) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* header ok? */
|
||||
if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_DH, PACKET_SUB_SIGNED)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* get hash out of packet */
|
||||
y = PACKET_SIZE;
|
||||
|
||||
/* init all bignums */
|
||||
if ((err = mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* load a and b */
|
||||
INPUT_BIGNUM(a, sig, x, y, siglen);
|
||||
INPUT_BIGNUM(b, sig, x, y, siglen);
|
||||
|
||||
/* load p and g */
|
||||
if ((err = mp_read_radix(p, sets[key->idx].prime, 16)) != CRYPT_OK) { goto error1; }
|
||||
if ((err = mp_read_radix(g, sets[key->idx].base, 16)) != CRYPT_OK) { goto error1; }
|
||||
|
||||
/* load m */
|
||||
if ((err = mp_read_unsigned_bin(m, (unsigned char *)hash, hashlen)) != CRYPT_OK) { goto error1; }
|
||||
|
||||
/* find g^m mod p */
|
||||
if ((err = mp_exptmod(g, m, p, m)) != CRYPT_OK) { goto error1; } /* m = g^m mod p */
|
||||
|
||||
/* find y^a * a^b */
|
||||
if ((err = mp_exptmod(key->y, a, p, tmp)) != CRYPT_OK) { goto error1; } /* tmp = y^a mod p */
|
||||
if ((err = mp_exptmod(a, b, p, a)) != CRYPT_OK) { goto error1; } /* a = a^b mod p */
|
||||
if ((err = mp_mulmod(a, tmp, p, a)) != CRYPT_OK) { goto error1; } /* a = y^a * a^b mod p */
|
||||
|
||||
/* y^a * a^b == g^m ??? */
|
||||
if (mp_cmp(a, m) == 0) {
|
||||
*stat = 1;
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
err = CRYPT_OK;
|
||||
goto done;
|
||||
error1:
|
||||
error:
|
||||
done:
|
||||
mp_clear_multi(tmp, m, g, p, b, a, NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* LTC_MDH */
|
||||
Reference in New Issue
Block a user