Merge pull request #237 from libtom/pr/dh-facelift-part1

DH facelift part 1
This commit is contained in:
karel-m 2017-06-22 14:16:36 +02:00 committed by GitHub
commit 316450c20e
19 changed files with 989 additions and 1384 deletions

View File

@ -891,8 +891,7 @@ static void time_dh(void)
{
dh_key key;
ulong64 t1, t2;
unsigned char buf[2][4096];
unsigned long i, x, y, z;
unsigned long i, x, y;
int err;
static unsigned long sizes[] = {768/8, 1024/8, 1536/8, 2048/8, 3072/8, 4096/8, 6144/8, 8192/8, 100000};
@ -908,29 +907,10 @@ static void time_dh(void)
t1 = t_read() - t1;
t2 += t1;
if (y < 15) {
dh_free(&key);
}
dh_free(&key);
}
t2 >>= 4;
fprintf(stderr, "DH-%4lu make_key took %15llu cycles\n", x*8, t2);
t2 = 0;
for (y = 0; y < 16; y++) {
t_start();
t1 = t_read();
z = sizeof(buf[1]);
if ((err = dh_encrypt_key(buf[0], 20, buf[1], &z, &yarrow_prng, find_prng("yarrow"), find_hash("sha1"),
&key)) != CRYPT_OK) {
fprintf(stderr, "\n\ndh_encrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
exit(EXIT_FAILURE);
}
t1 = t_read() - t1;
t2 += t1;
}
t2 >>= 4;
fprintf(stderr, "DH-%4lu encrypt_key took %15llu cycles\n", x*8, t2);
dh_free(&key);
}
}
#else

View File

@ -366,7 +366,7 @@ my $failure;
$failure ||= check_source() if $check_all || $check_source;
$failure ||= check_defines() if $check_all || $check_defines;
$failure ||= check_descriptors() if $check_all || $check_descriptors;
$failure ||= check_comments() if $check_comments; #XXX-FIXME not included in "--check-all"
$failure ||= check_comments() if $check_all || $check_comments;
$failure ||= process_makefiles(0) if $check_all || $check_makefiles;
$failure ||= process_makefiles(1) if $update_makefiles;

View File

@ -2051,15 +2051,27 @@
>
</File>
<File
RelativePath="src\pk\dh\dh_static.c"
RelativePath="src\pk\dh\dh_check_pubkey.c"
>
</File>
<File
RelativePath="src\pk\dh\dh_static.h"
RelativePath="src\pk\dh\dh_export.c"
>
</File>
<File
RelativePath="src\pk\dh\dh_sys.c"
RelativePath="src\pk\dh\dh_free.c"
>
</File>
<File
RelativePath="src\pk\dh\dh_import.c"
>
</File>
<File
RelativePath="src\pk\dh\dh_make_key.c"
>
</File>
<File
RelativePath="src\pk\dh\dh_shared_secret.c"
>
</File>
</Filter>

View File

@ -160,7 +160,8 @@ src/pk/asn1/der/teletex_string/der_length_teletex_string.o \
src/pk/asn1/der/utctime/der_decode_utctime.o src/pk/asn1/der/utctime/der_encode_utctime.o \
src/pk/asn1/der/utctime/der_length_utctime.o src/pk/asn1/der/utf8/der_decode_utf8_string.o \
src/pk/asn1/der/utf8/der_encode_utf8_string.o src/pk/asn1/der/utf8/der_length_utf8_string.o \
src/pk/dh/dh.o src/pk/dh/dh_static.o src/pk/dh/dh_sys.o src/pk/dsa/dsa_decrypt_key.o \
src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o src/pk/dh/dh_export.o src/pk/dh/dh_free.o \
src/pk/dh/dh_import.o src/pk/dh/dh_make_key.o src/pk/dh/dh_shared_secret.o src/pk/dsa/dsa_decrypt_key.o \
src/pk/dsa/dsa_encrypt_key.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o src/pk/dsa/dsa_import.o \
src/pk/dsa/dsa_import_radix.o src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_shared_secret.o \
src/pk/dsa/dsa_sign_hash.o src/pk/dsa/dsa_verify_hash.o src/pk/dsa/dsa_verify_key.o src/pk/ecc/ecc.o \

View File

@ -153,7 +153,8 @@ src/pk/asn1/der/teletex_string/der_length_teletex_string.obj \
src/pk/asn1/der/utctime/der_decode_utctime.obj src/pk/asn1/der/utctime/der_encode_utctime.obj \
src/pk/asn1/der/utctime/der_length_utctime.obj src/pk/asn1/der/utf8/der_decode_utf8_string.obj \
src/pk/asn1/der/utf8/der_encode_utf8_string.obj src/pk/asn1/der/utf8/der_length_utf8_string.obj \
src/pk/dh/dh.obj src/pk/dh/dh_static.obj src/pk/dh/dh_sys.obj src/pk/dsa/dsa_decrypt_key.obj \
src/pk/dh/dh.obj src/pk/dh/dh_check_pubkey.obj src/pk/dh/dh_export.obj src/pk/dh/dh_free.obj \
src/pk/dh/dh_import.obj src/pk/dh/dh_make_key.obj src/pk/dh/dh_shared_secret.obj src/pk/dsa/dsa_decrypt_key.obj \
src/pk/dsa/dsa_encrypt_key.obj src/pk/dsa/dsa_export.obj src/pk/dsa/dsa_free.obj src/pk/dsa/dsa_import.obj \
src/pk/dsa/dsa_import_radix.obj src/pk/dsa/dsa_make_key.obj src/pk/dsa/dsa_shared_secret.obj \
src/pk/dsa/dsa_sign_hash.obj src/pk/dsa/dsa_verify_hash.obj src/pk/dsa/dsa_verify_key.obj src/pk/ecc/ecc.obj \

View File

@ -170,7 +170,8 @@ src/pk/asn1/der/teletex_string/der_length_teletex_string.o \
src/pk/asn1/der/utctime/der_decode_utctime.o src/pk/asn1/der/utctime/der_encode_utctime.o \
src/pk/asn1/der/utctime/der_length_utctime.o src/pk/asn1/der/utf8/der_decode_utf8_string.o \
src/pk/asn1/der/utf8/der_encode_utf8_string.o src/pk/asn1/der/utf8/der_length_utf8_string.o \
src/pk/dh/dh.o src/pk/dh/dh_static.o src/pk/dh/dh_sys.o src/pk/dsa/dsa_decrypt_key.o \
src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o src/pk/dh/dh_export.o src/pk/dh/dh_free.o \
src/pk/dh/dh_import.o src/pk/dh/dh_make_key.o src/pk/dh/dh_shared_secret.o src/pk/dsa/dsa_decrypt_key.o \
src/pk/dsa/dsa_encrypt_key.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o src/pk/dsa/dsa_import.o \
src/pk/dsa/dsa_import_radix.o src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_shared_secret.o \
src/pk/dsa/dsa_sign_hash.o src/pk/dsa/dsa_verify_hash.o src/pk/dsa/dsa_verify_key.o src/pk/ecc/ecc.o \

View File

@ -276,7 +276,8 @@ src/pk/asn1/der/teletex_string/der_length_teletex_string.o \
src/pk/asn1/der/utctime/der_decode_utctime.o src/pk/asn1/der/utctime/der_encode_utctime.o \
src/pk/asn1/der/utctime/der_length_utctime.o src/pk/asn1/der/utf8/der_decode_utf8_string.o \
src/pk/asn1/der/utf8/der_encode_utf8_string.o src/pk/asn1/der/utf8/der_length_utf8_string.o \
src/pk/dh/dh.o src/pk/dh/dh_static.o src/pk/dh/dh_sys.o src/pk/dsa/dsa_decrypt_key.o \
src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o src/pk/dh/dh_export.o src/pk/dh/dh_free.o \
src/pk/dh/dh_import.o src/pk/dh/dh_make_key.o src/pk/dh/dh_shared_secret.o src/pk/dsa/dsa_decrypt_key.o \
src/pk/dsa/dsa_encrypt_key.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o src/pk/dsa/dsa_import.o \
src/pk/dsa/dsa_import_radix.o src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_shared_secret.o \
src/pk/dsa/dsa_sign_hash.o src/pk/dsa/dsa_verify_hash.o src/pk/dsa/dsa_verify_key.o src/pk/ecc/ecc.o \

View File

@ -183,17 +183,29 @@ 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_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);
@ -202,26 +214,13 @@ int dh_import(const unsigned char *in, unsigned long inlen, 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

View File

@ -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$ */

View File

@ -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$ */

62
src/pk/dh/dh_export.c Normal file
View File

@ -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$ */

43
src/pk/dh/dh_free.c Normal file
View File

@ -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$ */

97
src/pk/dh/dh_import.c Normal file
View File

@ -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$ */

175
src/pk/dh/dh_make_key.c Normal file
View File

@ -0,0 +1,175 @@
/* 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 (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)
{
void *p, *b;
int i, err;
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;
if ((err = mp_init_multi(&p, &b, NULL)) != CRYPT_OK) { return err; }
if ((err = mp_read_radix(b, ltc_dh_sets[i].base, 16)) != CRYPT_OK) { goto error; }
if ((err = mp_read_radix(p, ltc_dh_sets[i].prime, 16)) != 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 (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$ */

View File

@ -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$ */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -16,108 +16,220 @@
#define KEYSIZE 2048
#endif
int dh_test (void)
static int _prime_test(void)
{
unsigned char buf[3][4096], ch;
unsigned long x, y, z;
int stat, stat2;
dh_key usera, userb;
void *p, *g, *tmp;
int x, err, primality;
if ((err = mp_init_multi(&p, &g, &tmp, NULL)) != CRYPT_OK) { goto error; }
for (x = 0; ltc_dh_sets[x].size != 0; x++) {
if ((err = mp_read_radix(g, ltc_dh_sets[x].base, 16)) != CRYPT_OK) { goto error; }
if ((err = mp_read_radix(p, ltc_dh_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;
}
static int _dhparam_test(void)
{
dh_key k;
unsigned char buf[1024];
/* generated by: openssl dhparam -outform der -out dhparam.der 2048 */
unsigned char dhparam_der[] = {
0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0xae, 0xfe, 0x78, 0xce, 0x80, 0xd5, 0xd7,
0x8e, 0xcc, 0x4f, 0x0c, 0x1b, 0xb0, 0x95, 0x10, 0xe1, 0x41, 0x15, 0x53, 0x4d, 0x0e, 0x68, 0xb0,
0xf8, 0x5a, 0x41, 0x0e, 0x65, 0x2f, 0x9f, 0xac, 0x9c, 0x30, 0xb0, 0x76, 0xec, 0x02, 0xe9, 0x43,
0x55, 0x08, 0xb4, 0x20, 0x60, 0xd9, 0x52, 0xda, 0x2d, 0xab, 0x9a, 0xba, 0xe6, 0xcf, 0x11, 0xa7,
0x00, 0x44, 0xc2, 0x5e, 0xd1, 0xba, 0x9b, 0xaa, 0xfe, 0x03, 0xdd, 0xdc, 0xef, 0x41, 0x89, 0x9c,
0xac, 0x64, 0x13, 0xd9, 0x6a, 0x8a, 0x55, 0xa0, 0x5b, 0xff, 0x12, 0x92, 0x37, 0x52, 0x6a, 0x91,
0xa4, 0x6e, 0x9e, 0x61, 0xb7, 0xfe, 0xb0, 0x17, 0x8e, 0x67, 0x0f, 0x88, 0x46, 0xa7, 0x9e, 0xb1,
0xdb, 0x68, 0x77, 0x70, 0xb5, 0x77, 0xf2, 0x7e, 0x33, 0xb1, 0x3e, 0x10, 0xc4, 0x63, 0x36, 0xd0,
0x13, 0x27, 0xd3, 0x29, 0xc3, 0xb6, 0x5d, 0xf6, 0x5d, 0xa7, 0xd8, 0x25, 0x5c, 0x0b, 0x65, 0x99,
0xfa, 0xf9, 0x5f, 0x1d, 0xee, 0xd1, 0x86, 0x64, 0x7c, 0x44, 0xcb, 0xa0, 0x12, 0x52, 0x4c, 0xd4,
0x46, 0x81, 0xae, 0x07, 0xdb, 0xc7, 0x13, 0x29, 0xce, 0x9b, 0xcf, 0x1c, 0x06, 0xd2, 0x0f, 0x2d,
0xbb, 0x12, 0x33, 0xb9, 0xb1, 0x0f, 0x67, 0x5d, 0x3f, 0x0c, 0xe4, 0xfa, 0x67, 0x26, 0xe2, 0x89,
0xa2, 0xd5, 0x66, 0x29, 0x1c, 0xe2, 0x8e, 0xbb, 0x7b, 0xcb, 0xcc, 0x70, 0x7e, 0x4f, 0x0e, 0xd3,
0x5d, 0x64, 0x64, 0x1b, 0x27, 0xbb, 0xda, 0xa9, 0x08, 0x2b, 0x62, 0xd4, 0xca, 0xc3, 0x3a, 0x23,
0x39, 0x58, 0x57, 0xaf, 0x7b, 0x8b, 0x0c, 0x5b, 0x2e, 0xfc, 0x42, 0x57, 0x59, 0x39, 0x2e, 0x6d,
0x39, 0x97, 0xdb, 0x5b, 0x5c, 0xb9, 0x59, 0x71, 0x42, 0xf3, 0xcd, 0xea, 0xda, 0x86, 0x54, 0x86,
0x61, 0x8d, 0x93, 0x66, 0xc7, 0x65, 0xd1, 0x98, 0xcb, 0x02, 0x01, 0x02
};
/* text dump: openssl dh -inform DER -in dhparam.der -text
DH Parameters: (2048 bit)
prime:
00:ae:fe:78:ce:80:d5:d7:8e:cc:4f:0c:1b:b0:95:
10:e1:41:15:53:4d:0e:68:b0:f8:5a:41:0e:65:2f:
9f:ac:9c:30:b0:76:ec:02:e9:43:55:08:b4:20:60:
d9:52:da:2d:ab:9a:ba:e6:cf:11:a7:00:44:c2:5e:
d1:ba:9b:aa:fe:03:dd:dc:ef:41:89:9c:ac:64:13:
d9:6a:8a:55:a0:5b:ff:12:92:37:52:6a:91:a4:6e:
9e:61:b7:fe:b0:17:8e:67:0f:88:46:a7:9e:b1:db:
68:77:70:b5:77:f2:7e:33:b1:3e:10:c4:63:36:d0:
13:27:d3:29:c3:b6:5d:f6:5d:a7:d8:25:5c:0b:65:
99:fa:f9:5f:1d:ee:d1:86:64:7c:44:cb:a0:12:52:
4c:d4:46:81:ae:07:db:c7:13:29:ce:9b:cf:1c:06:
d2:0f:2d:bb:12:33:b9:b1:0f:67:5d:3f:0c:e4:fa:
67:26:e2:89:a2:d5:66:29:1c:e2:8e:bb:7b:cb:cc:
70:7e:4f:0e:d3:5d:64:64:1b:27:bb:da:a9:08:2b:
62:d4:ca:c3:3a:23:39:58:57:af:7b:8b:0c:5b:2e:
fc:42:57:59:39:2e:6d:39:97:db:5b:5c:b9:59:71:
42:f3:cd:ea:da:86:54:86:61:8d:93:66:c7:65:d1:
98:cb
generator: 2 (0x2)
*/
unsigned char prime[] = {
0xae, 0xfe, 0x78, 0xce, 0x80, 0xd5, 0xd7, 0x8e, 0xcc, 0x4f, 0x0c, 0x1b, 0xb0, 0x95,
0x10, 0xe1, 0x41, 0x15, 0x53, 0x4d, 0x0e, 0x68, 0xb0, 0xf8, 0x5a, 0x41, 0x0e, 0x65, 0x2f,
0x9f, 0xac, 0x9c, 0x30, 0xb0, 0x76, 0xec, 0x02, 0xe9, 0x43, 0x55, 0x08, 0xb4, 0x20, 0x60,
0xd9, 0x52, 0xda, 0x2d, 0xab, 0x9a, 0xba, 0xe6, 0xcf, 0x11, 0xa7, 0x00, 0x44, 0xc2, 0x5e,
0xd1, 0xba, 0x9b, 0xaa, 0xfe, 0x03, 0xdd, 0xdc, 0xef, 0x41, 0x89, 0x9c, 0xac, 0x64, 0x13,
0xd9, 0x6a, 0x8a, 0x55, 0xa0, 0x5b, 0xff, 0x12, 0x92, 0x37, 0x52, 0x6a, 0x91, 0xa4, 0x6e,
0x9e, 0x61, 0xb7, 0xfe, 0xb0, 0x17, 0x8e, 0x67, 0x0f, 0x88, 0x46, 0xa7, 0x9e, 0xb1, 0xdb,
0x68, 0x77, 0x70, 0xb5, 0x77, 0xf2, 0x7e, 0x33, 0xb1, 0x3e, 0x10, 0xc4, 0x63, 0x36, 0xd0,
0x13, 0x27, 0xd3, 0x29, 0xc3, 0xb6, 0x5d, 0xf6, 0x5d, 0xa7, 0xd8, 0x25, 0x5c, 0x0b, 0x65,
0x99, 0xfa, 0xf9, 0x5f, 0x1d, 0xee, 0xd1, 0x86, 0x64, 0x7c, 0x44, 0xcb, 0xa0, 0x12, 0x52,
0x4c, 0xd4, 0x46, 0x81, 0xae, 0x07, 0xdb, 0xc7, 0x13, 0x29, 0xce, 0x9b, 0xcf, 0x1c, 0x06,
0xd2, 0x0f, 0x2d, 0xbb, 0x12, 0x33, 0xb9, 0xb1, 0x0f, 0x67, 0x5d, 0x3f, 0x0c, 0xe4, 0xfa,
0x67, 0x26, 0xe2, 0x89, 0xa2, 0xd5, 0x66, 0x29, 0x1c, 0xe2, 0x8e, 0xbb, 0x7b, 0xcb, 0xcc,
0x70, 0x7e, 0x4f, 0x0e, 0xd3, 0x5d, 0x64, 0x64, 0x1b, 0x27, 0xbb, 0xda, 0xa9, 0x08, 0x2b,
0x62, 0xd4, 0xca, 0xc3, 0x3a, 0x23, 0x39, 0x58, 0x57, 0xaf, 0x7b, 0x8b, 0x0c, 0x5b, 0x2e,
0xfc, 0x42, 0x57, 0x59, 0x39, 0x2e, 0x6d, 0x39, 0x97, 0xdb, 0x5b, 0x5c, 0xb9, 0x59, 0x71,
0x42, 0xf3, 0xcd, 0xea, 0xda, 0x86, 0x54, 0x86, 0x61, 0x8d, 0x93, 0x66, 0xc7, 0x65, 0xd1,
0x98, 0xcb
};
DO(dh_make_key_dhparam(&yarrow_prng, find_prng ("yarrow"), dhparam_der, sizeof(dhparam_der), &k));
if (mp_unsigned_bin_size(k.prime) > sizeof(buf)) {
printf("dhparam_test: short buf\n");
dh_free(&k);
return CRYPT_ERROR;
}
DO(mp_to_unsigned_bin(k.prime, buf));
if (compare_testvector(buf, sizeof(prime), prime, sizeof(prime), "dhparam_test", 1)) {
printf("dhparam_test: prime mismatch\n");
dh_free(&k);
return CRYPT_ERROR;
}
if (mp_cmp_d(k.base, 2) != LTC_MP_EQ) {
printf("dhparam_test: base mismatch\n");
dh_free(&k);
return CRYPT_ERROR;
}
dh_free(&k);
return CRYPT_OK;
}
static int _basic_test(void)
{
unsigned char buf[3][4096];
unsigned long x, y, z;
int size;
dh_key usera, userb;
if (register_prng(&yarrow_desc) == -1) {
printf("Error registering yarrow PRNG\n");
exit(-1);
return CRYPT_ERROR;
}
if (register_hash(&md5_desc) == -1) {
printf("Error registering md5 hash\n");
exit(-1);
return CRYPT_ERROR;
}
DO(dh_compat_test());
/* make up two keys */
DO(dh_make_key (&yarrow_prng, find_prng ("yarrow"), KEYSIZE/8, &usera));
DO(dh_make_key (&yarrow_prng, find_prng ("yarrow"), KEYSIZE/8, &userb));
/* make the shared secret */
x = KEYSIZE;
DO(dh_shared_secret (&usera, &userb, buf[0], &x));
/* make up two keys */
DO(dh_make_key (&yarrow_prng, find_prng ("yarrow"), KEYSIZE/8, &usera));
DO(dh_make_key (&yarrow_prng, find_prng ("yarrow"), KEYSIZE/8, &userb));
/* make the shared secret */
x = KEYSIZE;
DO(dh_shared_secret (&usera, &userb, buf[0], &x));
y = KEYSIZE;
DO(dh_shared_secret (&userb, &usera, buf[1], &y));
if (y != x) {
fprintf(stderr, "DH Shared keys are not same size.\n");
dh_free (&usera);
dh_free (&userb);
return 1;
}
if (memcmp (buf[0], buf[1], x)) {
fprintf(stderr, "DH Shared keys not same contents.\n");
dh_free (&usera);
dh_free (&userb);
return 1;
}
/* now export userb */
y = KEYSIZE;
DO(dh_export (buf[1], &y, PK_PUBLIC, &userb));
dh_free (&userb);
/* import and make the shared secret again */
DO(dh_import (buf[1], y, &userb));
z = KEYSIZE;
DO(dh_shared_secret (&usera, &userb, buf[2], &z));
dh_free (&usera);
dh_free (&userb);
if (z != x) {
fprintf(stderr, "failed. Size don't match?\n");
return 1;
}
if (memcmp (buf[0], buf[2], x)) {
fprintf(stderr, "Failed. Content didn't match.\n");
return 1;
}
/* test encrypt_key */
dh_make_key (&yarrow_prng, find_prng ("yarrow"), KEYSIZE/8, &usera);
for (ch = 0; ch < 16; ch++) {
buf[0][ch] = ch;
}
y = sizeof (buf[1]);
DO(dh_encrypt_key (buf[0], 16, buf[1], &y, &yarrow_prng, find_prng ("yarrow"), find_hash ("md5"), &usera));
zeromem (buf[0], sizeof (buf[0]));
x = sizeof (buf[0]);
DO(dh_decrypt_key (buf[1], y, buf[0], &x, &usera));
if (x != 16) {
fprintf(stderr, "Failed (length)\n");
dh_free (&usera);
return 1;
}
for (ch = 0; ch < 16; ch++)
if (buf[0][ch] != ch) {
fprintf(stderr, "Failed (contents)\n");
y = KEYSIZE;
DO(dh_shared_secret (&userb, &usera, buf[1], &y));
if (y != x) {
fprintf(stderr, "DH Shared keys are not same size.\n");
dh_free (&usera);
return 1;
}
dh_free (&userb);
return CRYPT_ERROR;
}
if (memcmp (buf[0], buf[1], x)) {
fprintf(stderr, "DH Shared keys not same contents.\n");
dh_free (&usera);
dh_free (&userb);
return CRYPT_ERROR;
}
/* test sign_hash */
for (ch = 0; ch < 16; ch++) {
buf[0][ch] = ch;
}
x = sizeof (buf[1]);
DO(dh_sign_hash (buf[0], 16, buf[1], &x, &yarrow_prng, find_prng ("yarrow"), &usera));
DO(dh_verify_hash (buf[1], x, buf[0], 16, &stat, &usera));
buf[0][0] ^= 1;
DO(dh_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera));
dh_free (&usera);
if (!(stat == 1 && stat2 == 0)) {
fprintf(stderr, "dh_sign/verify_hash %d %d", stat, stat2);
return 1;
}
return 0;
/* now export userb */
y = KEYSIZE;
DO(dh_export (buf[1], &y, PK_PUBLIC, &userb));
dh_free (&userb);
/* import and make the shared secret again */
DO(dh_import (buf[1], y, &userb));
z = KEYSIZE;
DO(dh_shared_secret (&usera, &userb, buf[2], &z));
dh_free (&usera);
dh_free (&userb);
if (z != x) {
fprintf(stderr, "failed. Size don't match?\n");
return CRYPT_ERROR;
}
if (memcmp (buf[0], buf[2], x)) {
fprintf(stderr, "Failed. Content didn't match.\n");
return CRYPT_ERROR;
}
for (x = 0; ltc_dh_sets[x].size != 0; x++) {
DO(dh_make_key(&yarrow_prng, find_prng ("yarrow"), ltc_dh_sets[x].size, &usera));
size = dh_get_groupsize(&usera);
dh_free(&usera);
if (size != ltc_dh_sets[x].size) {
fprintf(stderr, "dh_groupsize mismatch %d %d\n", size, ltc_dh_sets[x].size);
return CRYPT_ERROR;
}
}
return CRYPT_OK;
}
int dh_test(void)
{
int fails = 0;
if (_prime_test() != CRYPT_OK) fails++;
if (_basic_test() != CRYPT_OK) fails++;
if (_dhparam_test() != CRYPT_OK) fails++;
return fails > 0 ? CRYPT_FAIL_TESTVECTOR : CRYPT_OK;
}
#else
int dh_test(void)