diff --git a/demos/timing.c b/demos/timing.c
index b36ba61..aa7c9a5 100644
--- a/demos/timing.c
+++ b/demos/timing.c
@@ -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
diff --git a/helper.pl b/helper.pl
index b66dbce..ab41a51 100755
--- a/helper.pl
+++ b/helper.pl
@@ -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;
diff --git a/libtomcrypt_VS2008.vcproj b/libtomcrypt_VS2008.vcproj
index 6f92d28..2516240 100644
--- a/libtomcrypt_VS2008.vcproj
+++ b/libtomcrypt_VS2008.vcproj
@@ -2051,15 +2051,27 @@
>
+
+
+
+
+
+
diff --git a/makefile.mingw b/makefile.mingw
index 67b2802..04ad30b 100644
--- a/makefile.mingw
+++ b/makefile.mingw
@@ -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 \
diff --git a/makefile.msvc b/makefile.msvc
index 8395ed5..804c858 100644
--- a/makefile.msvc
+++ b/makefile.msvc
@@ -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 \
diff --git a/makefile.unix b/makefile.unix
index 73b4bf3..88f88a0 100644
--- a/makefile.unix
+++ b/makefile.unix
@@ -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 \
diff --git a/makefile_include.mk b/makefile_include.mk
index c82095c..daf7657 100644
--- a/makefile_include.mk
+++ b/makefile_include.mk
@@ -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 \
diff --git a/src/headers/tomcrypt_pk.h b/src/headers/tomcrypt_pk.h
index aa00be1..1ff657d 100644
--- a/src/headers/tomcrypt_pk.h
+++ b/src/headers/tomcrypt_pk.h
@@ -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
diff --git a/src/pk/dh/dh.c b/src/pk/dh/dh.c
index b907540..763b007 100644
--- a/src/pk/dh/dh.c
+++ b/src/pk/dh/dh.c
@@ -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$ */
diff --git a/src/pk/dh/dh_check_pubkey.c b/src/pk/dh/dh_check_pubkey.c
new file mode 100644
index 0000000..c77e4bd
--- /dev/null
+++ b/src/pk/dh/dh_check_pubkey.c
@@ -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$ */
diff --git a/src/pk/dh/dh_export.c b/src/pk/dh/dh_export.c
new file mode 100644
index 0000000..6a02a89
--- /dev/null
+++ b/src/pk/dh/dh_export.c
@@ -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$ */
diff --git a/src/pk/dh/dh_free.c b/src/pk/dh/dh_free.c
new file mode 100644
index 0000000..8ca1f65
--- /dev/null
+++ b/src/pk/dh/dh_free.c
@@ -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$ */
diff --git a/src/pk/dh/dh_import.c b/src/pk/dh/dh_import.c
new file mode 100644
index 0000000..aa16842
--- /dev/null
+++ b/src/pk/dh/dh_import.c
@@ -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$ */
diff --git a/src/pk/dh/dh_make_key.c b/src/pk/dh/dh_make_key.c
new file mode 100644
index 0000000..cbaea88
--- /dev/null
+++ b/src/pk/dh/dh_make_key.c
@@ -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$ */
diff --git a/src/pk/dh/dh_shared_secret.c b/src/pk/dh/dh_shared_secret.c
new file mode 100644
index 0000000..1eb69fb
--- /dev/null
+++ b/src/pk/dh/dh_shared_secret.c
@@ -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$ */
diff --git a/src/pk/dh/dh_static.c b/src/pk/dh/dh_static.c
deleted file mode 100644
index d5be03c..0000000
--- a/src/pk/dh/dh_static.c
+++ /dev/null
@@ -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 */
diff --git a/src/pk/dh/dh_static.h b/src/pk/dh/dh_static.h
deleted file mode 100644
index 5a47ee0..0000000
--- a/src/pk/dh/dh_static.h
+++ /dev/null
@@ -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 */
diff --git a/src/pk/dh/dh_sys.c b/src/pk/dh/dh_sys.c
deleted file mode 100644
index 8a42c96..0000000
--- a/src/pk/dh/dh_sys.c
+++ /dev/null
@@ -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 */
diff --git a/tests/dh_test.c b/tests/dh_test.c
index efca705..3374c80 100644
--- a/tests/dh_test.c
+++ b/tests/dh_test.c
@@ -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)