Browse Source

Merge pull request #227 from libtom/pr/dh_make_key_ex

DH facelift part 2 (dh_make_key_ex & co.)
Steffen Jaeckel 8 years ago
parent
commit
292f42d3c0

+ 7 - 2
demos/timing.c

@@ -889,7 +889,7 @@ static void time_katja(void) { fprintf(stderr, "NO Katja\n"); }
 /* time various DH operations */
 /* time various DH operations */
 static void time_dh(void)
 static void time_dh(void)
 {
 {
-   dh_key key;
+   dh_key key = LTC_DH_KEY_INITIALIZER;
    ulong64 t1, t2;
    ulong64 t1, t2;
    unsigned long i, x, y;
    unsigned long i, x, y;
    int           err;
    int           err;
@@ -898,9 +898,14 @@ static void time_dh(void)
    for (x = sizes[i=0]; x < 100000; x = sizes[++i]) {
    for (x = sizes[i=0]; x < 100000; x = sizes[++i]) {
        t2 = 0;
        t2 = 0;
        for (y = 0; y < 16; y++) {
        for (y = 0; y < 16; y++) {
+           if((err = dh_set_pg_groupsize(x, &key)) != CRYPT_OK) {
+              fprintf(stderr, "\n\ndh_set_pg_groupsize says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
+              exit(EXIT_FAILURE);
+           }
+
            t_start();
            t_start();
            t1 = t_read();
            t1 = t_read();
-           if ((err = dh_make_key(&yarrow_prng, find_prng("yarrow"), x, &key)) != CRYPT_OK) {
+           if ((err = dh_make_key(&yarrow_prng, find_prng("yarrow"), &key)) != CRYPT_OK) {
               fprintf(stderr, "\n\ndh_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
               fprintf(stderr, "\n\ndh_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK));
               exit(EXIT_FAILURE);
               exit(EXIT_FAILURE);
            }
            }

+ 8 - 0
libtomcrypt_VS2008.vcproj

@@ -2062,6 +2062,10 @@
 					RelativePath="src\pk\dh\dh_export.c"
 					RelativePath="src\pk\dh\dh_export.c"
 					>
 					>
 				</File>
 				</File>
+				<File
+					RelativePath="src\pk\dh\dh_export_key.c"
+					>
+				</File>
 				<File
 				<File
 					RelativePath="src\pk\dh\dh_free.c"
 					RelativePath="src\pk\dh\dh_free.c"
 					>
 					>
@@ -2074,6 +2078,10 @@
 					RelativePath="src\pk\dh\dh_make_key.c"
 					RelativePath="src\pk\dh\dh_make_key.c"
 					>
 					>
 				</File>
 				</File>
+				<File
+					RelativePath="src\pk\dh\dh_set.c"
+					>
+				</File>
 				<File
 				<File
 					RelativePath="src\pk\dh\dh_shared_secret.c"
 					RelativePath="src\pk\dh\dh_shared_secret.c"
 					>
 					>

+ 6 - 5
makefile.mingw

@@ -160,11 +160,12 @@ 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_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/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/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_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 \
+src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o src/pk/dh/dh_export.o src/pk/dh/dh_export_key.o \
+src/pk/dh/dh_free.o src/pk/dh/dh_import.o src/pk/dh/dh_make_key.o src/pk/dh/dh_set.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 \
 src/pk/ecc/ecc_ansi_x963_export.o src/pk/ecc/ecc_ansi_x963_import.o src/pk/ecc/ecc_decrypt_key.o \
 src/pk/ecc/ecc_ansi_x963_export.o src/pk/ecc/ecc_ansi_x963_import.o src/pk/ecc/ecc_decrypt_key.o \
 src/pk/ecc/ecc_encrypt_key.o src/pk/ecc/ecc_export.o src/pk/ecc/ecc_free.o src/pk/ecc/ecc_get_size.o \
 src/pk/ecc/ecc_encrypt_key.o src/pk/ecc/ecc_export.o src/pk/ecc/ecc_free.o src/pk/ecc/ecc_get_size.o \
 src/pk/ecc/ecc_import.o src/pk/ecc/ecc_make_key.o src/pk/ecc/ecc_shared_secret.o \
 src/pk/ecc/ecc_import.o src/pk/ecc/ecc_make_key.o src/pk/ecc/ecc_shared_secret.o \

+ 6 - 5
makefile.msvc

@@ -153,11 +153,12 @@ 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_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/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/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_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 \
+src/pk/dh/dh.obj src/pk/dh/dh_check_pubkey.obj src/pk/dh/dh_export.obj src/pk/dh/dh_export_key.obj \
+src/pk/dh/dh_free.obj src/pk/dh/dh_import.obj src/pk/dh/dh_make_key.obj src/pk/dh/dh_set.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 \
 src/pk/ecc/ecc_ansi_x963_export.obj src/pk/ecc/ecc_ansi_x963_import.obj src/pk/ecc/ecc_decrypt_key.obj \
 src/pk/ecc/ecc_ansi_x963_export.obj src/pk/ecc/ecc_ansi_x963_import.obj src/pk/ecc/ecc_decrypt_key.obj \
 src/pk/ecc/ecc_encrypt_key.obj src/pk/ecc/ecc_export.obj src/pk/ecc/ecc_free.obj src/pk/ecc/ecc_get_size.obj \
 src/pk/ecc/ecc_encrypt_key.obj src/pk/ecc/ecc_export.obj src/pk/ecc/ecc_free.obj src/pk/ecc/ecc_get_size.obj \
 src/pk/ecc/ecc_import.obj src/pk/ecc/ecc_make_key.obj src/pk/ecc/ecc_shared_secret.obj \
 src/pk/ecc/ecc_import.obj src/pk/ecc/ecc_make_key.obj src/pk/ecc/ecc_shared_secret.obj \

+ 6 - 5
makefile.unix

@@ -170,11 +170,12 @@ 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_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/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/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_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 \
+src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o src/pk/dh/dh_export.o src/pk/dh/dh_export_key.o \
+src/pk/dh/dh_free.o src/pk/dh/dh_import.o src/pk/dh/dh_make_key.o src/pk/dh/dh_set.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 \
 src/pk/ecc/ecc_ansi_x963_export.o src/pk/ecc/ecc_ansi_x963_import.o src/pk/ecc/ecc_decrypt_key.o \
 src/pk/ecc/ecc_ansi_x963_export.o src/pk/ecc/ecc_ansi_x963_import.o src/pk/ecc/ecc_decrypt_key.o \
 src/pk/ecc/ecc_encrypt_key.o src/pk/ecc/ecc_export.o src/pk/ecc/ecc_free.o src/pk/ecc/ecc_get_size.o \
 src/pk/ecc/ecc_encrypt_key.o src/pk/ecc/ecc_export.o src/pk/ecc/ecc_free.o src/pk/ecc/ecc_get_size.o \
 src/pk/ecc/ecc_import.o src/pk/ecc/ecc_make_key.o src/pk/ecc/ecc_shared_secret.o \
 src/pk/ecc/ecc_import.o src/pk/ecc/ecc_make_key.o src/pk/ecc/ecc_shared_secret.o \

+ 6 - 5
makefile_include.mk

@@ -276,11 +276,12 @@ 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_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/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/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_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 \
+src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o src/pk/dh/dh_export.o src/pk/dh/dh_export_key.o \
+src/pk/dh/dh_free.o src/pk/dh/dh_import.o src/pk/dh/dh_make_key.o src/pk/dh/dh_set.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 \
 src/pk/ecc/ecc_ansi_x963_export.o src/pk/ecc/ecc_ansi_x963_import.o src/pk/ecc/ecc_decrypt_key.o \
 src/pk/ecc/ecc_ansi_x963_export.o src/pk/ecc/ecc_ansi_x963_import.o src/pk/ecc/ecc_decrypt_key.o \
 src/pk/ecc/ecc_encrypt_key.o src/pk/ecc/ecc_export.o src/pk/ecc/ecc_free.o src/pk/ecc/ecc_get_size.o \
 src/pk/ecc/ecc_encrypt_key.o src/pk/ecc/ecc_export.o src/pk/ecc/ecc_free.o src/pk/ecc/ecc_get_size.o \
 src/pk/ecc/ecc_import.o src/pk/ecc/ecc_make_key.o src/pk/ecc/ecc_shared_secret.o \
 src/pk/ecc/ecc_import.o src/pk/ecc/ecc_make_key.o src/pk/ecc/ecc_shared_secret.o \

+ 18 - 4
src/headers/tomcrypt_pk.h

@@ -213,18 +213,32 @@ typedef struct {
     void *prime;
     void *prime;
 } dh_key;
 } dh_key;
 
 
-int dh_get_groupsize(dh_key *key);
+#define LTC_DH_KEY_INITIALIZER { PK_PUBLIC, NULL, NULL, NULL, NULL }
 
 
-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_get_groupsize(dh_key *key);
 
 
 int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key);
 int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key);
 int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key);
 int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key);
 
 
+int dh_set_pg(const unsigned char *p, unsigned long plen,
+              const unsigned char *g, unsigned long glen,
+              dh_key *key);
+int dh_set_pg_dhparam(const unsigned char *dhparam, unsigned long dhparamlen, dh_key *key);
+int dh_set_pg_groupsize(int groupsize, dh_key *key);
+
+int dh_set_key(const unsigned char *pub, unsigned long publen,
+               const unsigned char *priv, unsigned long privlen,
+               dh_key *key);
+int dh_make_key(prng_state *prng, int wprng, dh_key *key);
+
 int dh_shared_secret(dh_key        *private_key, dh_key        *public_key,
 int dh_shared_secret(dh_key        *private_key, dh_key        *public_key,
                      unsigned char *out,         unsigned long *outlen);
                      unsigned char *out,         unsigned long *outlen);
 
 
+void dh_free(dh_key *key);
+
+int dh_export_key(void *out, unsigned long *outlen,
+                  int type, dh_key *key);
+
 #ifdef LTC_SOURCE
 #ifdef LTC_SOURCE
 /* internal helper functions */
 /* internal helper functions */
 int dh_check_pubkey(dh_key *key);
 int dh_check_pubkey(dh_key *key);

+ 47 - 0
src/pk/dh/dh_export_key.c

@@ -0,0 +1,47 @@
+/* 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
+
+/**
+  Binary export a DH key to a buffer
+  @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_key(void *out, unsigned long *outlen, int type, dh_key *key)
+{
+   unsigned long len;
+   void *k;
+
+   LTC_ARGCHK(out    != NULL);
+   LTC_ARGCHK(outlen != NULL);
+   LTC_ARGCHK(key    != NULL);
+
+   k = (type == PK_PRIVATE) ? key->x : key->y;
+   len = mp_unsigned_bin_size(k);
+
+   if (*outlen < len) {
+      *outlen = len;
+      return CRYPT_BUFFER_OVERFLOW;
+   }
+   *outlen = len;
+
+   return mp_to_unsigned_bin(k, out);
+}
+
+#endif /* LTC_MDH */
+
+/* ref:         $Format:%D$ */
+/* git commit:  $Format:%H$ */
+/* commit time: $Format:%ai$ */

+ 8 - 76
src/pk/dh/dh_make_key.c

@@ -42,31 +42,25 @@ static int _dh_groupsize_to_keysize(int groupsize)
    }
    }
 }
 }
 
 
-static int _dh_make_key(prng_state *prng, int wprng, void *prime, void *base, dh_key *key)
+int dh_make_key(prng_state *prng, int wprng, dh_key *key)
 {
 {
    unsigned char *buf;
    unsigned char *buf;
    unsigned long keysize;
    unsigned long keysize;
    int err, max_iterations = PK_MAX_RETRIES;
    int err, max_iterations = PK_MAX_RETRIES;
 
 
-   LTC_ARGCHK(key   != NULL);
-   LTC_ARGCHK(prng  != NULL);
-   LTC_ARGCHK(prime != NULL);
-   LTC_ARGCHK(base  != NULL);
+   LTC_ARGCHK(key         != NULL);
+   LTC_ARGCHK(key->x      != NULL);
+   LTC_ARGCHK(key->y      != NULL);
+   LTC_ARGCHK(key->base   != NULL);
+   LTC_ARGCHK(key->prime  != NULL);
+   LTC_ARGCHK(ltc_mp.name != NULL);
+   LTC_ARGCHK(prng        != NULL);
 
 
    /* good prng? */
    /* good prng? */
    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
       return err;
       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));
    keysize = _dh_groupsize_to_keysize(mp_unsigned_bin_size(key->prime));
    if (keysize == 0) {
    if (keysize == 0) {
       err = CRYPT_INVALID_KEYSIZE;
       err = CRYPT_INVALID_KEYSIZE;
@@ -106,68 +100,6 @@ freemp:
    return err;
    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 */
 #endif /* LTC_MDH */
 
 
 /* ref:         $Format:%D$ */
 /* ref:         $Format:%D$ */

+ 186 - 0
src/pk/dh/dh_set.c

@@ -0,0 +1,186 @@
+/* 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 DH key parts p and g from raw numbers
+
+  @param p       DH's p (prime)
+  @param plen    DH's p's length
+  @param g       DH's g (group)
+  @param glen    DH's g's length
+  @param key     [out] the destination for the imported key
+  @return CRYPT_OK if successful
+*/
+int dh_set_pg(const unsigned char *p, unsigned long plen,
+              const unsigned char *g, unsigned long glen,
+              dh_key *key)
+{
+   int err;
+
+   LTC_ARGCHK(key         != NULL);
+   LTC_ARGCHK(key->x      == NULL);
+   LTC_ARGCHK(key->y      == NULL);
+   LTC_ARGCHK(key->base   == NULL);
+   LTC_ARGCHK(key->prime  == NULL);
+   LTC_ARGCHK(p           != NULL);
+   LTC_ARGCHK(g           != NULL);
+   LTC_ARGCHK(ltc_mp.name != NULL);
+
+   if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) {
+      return err;
+   }
+
+   if ((err = mp_read_unsigned_bin(key->base, (unsigned char*)g, glen)) != CRYPT_OK)     { goto LBL_ERR; }
+   if ((err = mp_read_unsigned_bin(key->prime, (unsigned char*)p, plen)) != CRYPT_OK)  { goto LBL_ERR; }
+
+   return CRYPT_OK;
+
+LBL_ERR:
+   dh_free(key);
+   return err;
+}
+
+/**
+  Import DH key parts p and g from dhparam
+
+      dhparam data: openssl dhparam -outform DER -out dhparam.der 2048
+
+  @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_set_pg_dhparam(const unsigned char *dhparam, unsigned long dhparamlen, dh_key *key)
+{
+   int err;
+
+   LTC_ARGCHK(key         != NULL);
+   LTC_ARGCHK(key->x      == NULL);
+   LTC_ARGCHK(key->y      == NULL);
+   LTC_ARGCHK(key->base   == NULL);
+   LTC_ARGCHK(key->prime  == NULL);
+   LTC_ARGCHK(ltc_mp.name != NULL);
+   LTC_ARGCHK(dhparam     != NULL);
+   LTC_ARGCHK(dhparamlen  > 0);
+
+   if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = der_decode_sequence_multi(dhparam, dhparamlen,
+                                        LTC_ASN1_INTEGER, 1UL, key->prime,
+                                        LTC_ASN1_INTEGER, 1UL, key->base,
+                                        LTC_ASN1_EOL,     0UL, NULL)) != CRYPT_OK) {
+      goto LBL_ERR;
+   }
+
+   return CRYPT_OK;
+
+LBL_ERR:
+   dh_free(key);
+   return err;
+}
+
+/**
+  Import DH key parts p and g from built-in DH groups
+
+  @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_set_pg_groupsize(int groupsize, dh_key *key)
+{
+   int err, i;
+
+   LTC_ARGCHK(key         != NULL);
+   LTC_ARGCHK(key->x      == NULL);
+   LTC_ARGCHK(key->y      == NULL);
+   LTC_ARGCHK(key->base   == NULL);
+   LTC_ARGCHK(key->prime  == NULL);
+   LTC_ARGCHK(ltc_mp.name != NULL);
+   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(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) {
+      return err;
+   }
+   if ((err = mp_read_radix(key->base, ltc_dh_sets[i].base, 16)) != CRYPT_OK)  { goto LBL_ERR; }
+   if ((err = mp_read_radix(key->prime, ltc_dh_sets[i].prime, 16)) != CRYPT_OK) { goto LBL_ERR; }
+
+   return CRYPT_OK;
+
+LBL_ERR:
+   dh_free(key);
+   return err;
+}
+
+/**
+  Import DH key parts pub and priv from raw numbers
+
+  @param pub     DH's pub (public key) (can be NULL if priv is valid)
+  @param publen  DH's pub's length
+  @param priv    DH's priv (private key) (can be NULL if pub is valid)
+  @param privlen DH's priv's length
+  @param key     [out] the destination for the imported key
+  @return CRYPT_OK if successful
+*/
+int dh_set_key(const unsigned char *pub, unsigned long publen,
+               const unsigned char *priv, unsigned long privlen,
+               dh_key *key)
+{
+   int err;
+
+   LTC_ARGCHK(key         != NULL);
+   LTC_ARGCHK(key->x      != NULL);
+   LTC_ARGCHK(key->y      != NULL);
+   LTC_ARGCHK(key->base   != NULL);
+   LTC_ARGCHK(key->prime  != NULL);
+   LTC_ARGCHK(ltc_mp.name != NULL);
+
+   if(priv == NULL) {
+      if ((err = mp_read_unsigned_bin(key->y, (unsigned char*)pub, publen)) != CRYPT_OK)         { goto LBL_ERR; }
+      key->type = PK_PUBLIC;
+      mp_clear(key->x);
+      key->x = NULL;
+   }
+   else {
+      if ((err = mp_read_unsigned_bin(key->x, (unsigned char*)priv, privlen)) != CRYPT_OK)         { goto LBL_ERR; }
+      if (pub != NULL) {
+         if ((err = mp_read_unsigned_bin(key->y, (unsigned char*)pub, publen)) != CRYPT_OK)         { goto LBL_ERR; }
+      }
+      else {
+         /* compute y value */
+         if ((err = mp_exptmod(key->base, key->x, key->prime, key->y)) != CRYPT_OK)  { goto LBL_ERR; }
+      }
+      key->type = PK_PRIVATE;
+   }
+
+   /* check public key */
+   if ((err = dh_check_pubkey(key)) != CRYPT_OK) {
+      goto LBL_ERR;
+   }
+
+   return CRYPT_OK;
+
+LBL_ERR:
+   dh_free(key);
+   return err;
+}
+
+#endif /* LTC_MDH */
+
+/* ref:         $Format:%D$ */
+/* git commit:  $Format:%H$ */
+/* commit time: $Format:%ai$ */

+ 283 - 15
tests/dh_test.c

@@ -60,7 +60,7 @@ done:
 
 
 static int _dhparam_test(void)
 static int _dhparam_test(void)
 {
 {
-   dh_key k;
+   dh_key k = LTC_DH_KEY_INITIALIZER;
    unsigned char buf[1024];
    unsigned char buf[1024];
    /* generated by: openssl dhparam -outform der -out dhparam.der 2048 */
    /* generated by: openssl dhparam -outform der -out dhparam.der 2048 */
    unsigned char dhparam_der[] = {
    unsigned char dhparam_der[] = {
@@ -126,7 +126,8 @@ static int _dhparam_test(void)
       0x98, 0xcb
       0x98, 0xcb
    };
    };
 
 
-   DO(dh_make_key_dhparam(&yarrow_prng, find_prng ("yarrow"), dhparam_der, sizeof(dhparam_der), &k));
+   DO(dh_set_pg_dhparam(dhparam_der, sizeof(dhparam_der), &k));
+   DO(dh_make_key(&yarrow_prng, find_prng ("yarrow"), &k));
    if (mp_unsigned_bin_size(k.prime) > sizeof(buf)) {
    if (mp_unsigned_bin_size(k.prime) > sizeof(buf)) {
       printf("dhparam_test: short buf\n");
       printf("dhparam_test: short buf\n");
       dh_free(&k);
       dh_free(&k);
@@ -147,25 +148,289 @@ static int _dhparam_test(void)
    return CRYPT_OK;
    return CRYPT_OK;
 }
 }
 
 
+static int _radix_test(void)
+{
+   dh_key k1 = LTC_DH_KEY_INITIALIZER;
+   dh_key k2 = LTC_DH_KEY_INITIALIZER;
+   dh_key k3 = LTC_DH_KEY_INITIALIZER;
+   unsigned char buf[4096];
+   unsigned long len;
+   int i, j;
+   /* RADIX 16 */
+   char *ghex = "2";
+   char *phex = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22"
+                "514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6"
+                "F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+                "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB"
+                "9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E8603"
+                "9B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
+                "15728E5A8AACAA68FFFFFFFFFFFFFFFF";
+   char *xhex = "A6681ADC386CE944C3DED9A7301DCC9C518250E3EDB62F959198F8DC0057DD6FB57ABAFD788198B1";
+   char *yhex = "39046632C834418DFA07B3091538B614D1FB5DBB785C0FBEA3B98B295BC0CD076A88D9452141A269"
+                "E8BAEB1DD654EBA03A5705318D129754CDF4003A8C399240FBB8F162490F6F0DC70E414B6FEE8808"
+                "6AFAA48E9F3A248EDC093452663D34E0E809D4F6BADBB36F80B6813EBF7C3281B862209E5604BDEA"
+                "8B8F5F7BFDC3EEB7ADB73048289BCEA0F5A5CDEE7DF91CD1F0BA632F06DBE9BA7EF014B84B02D497"
+                "CA7D0C60F734752A649DA496946B4E531B30D9F82EDD855636C0B0F2AE232E4186454E8887BB423E"
+                "32A5A2495EACBA99620ACD03A38345EBB6735E62330A8EE9AA6C8370410F5CD45AF37EE90A0DA95B"
+                "E96FC939E88FE0BD2CD09FC8F524208C";
+   /* RADIX 47 */
+   char *gr47 = "2";
+   char *pr47 = "F27Mg1SadOFIRbDOJ5dHgHiVF02Z1LHHQ6G5SLG2U8aTdfH1ETk4GARRE7WW99dBUBLb9e2OHFIaSM1A"
+                "ag2LNNjgYa9I9CjQGJihL3J7A2SGQe8j5Ch8EHMj5jVbAYDiQKhhPhM6Hc56fKS40GUfJkGO7KJ6EXZQ"
+                "VgbSa2AkPC65F91g0PaYie8AGNVaFKaV9HOQf3ia1iW4i6eCOB9CcBbH7TbQij8AEgjZ0VRBcLKc6UYO"
+                "1Zc3I2Jc0h1H2HBEH8ONI3OYBbaPV6XhAd8WCc60D0RDBU3H9U7cWL28a0c90XNO0dh5RXEFBbUCE2ZG"
+                "gh9XQSVIHkVbFIS5F5IGVOkiWAVc9i8BHB2V0UbGW6UdRTZVV";
+   char *xr47 = "6bhO7O9NWFRgEMjdU0Y5POj3c1JP15MYEdIg3FO1PEjUY2aGYNSXcaF01R";
+   char *yr47 = "3GNPNWEYfKML1cIbI7Cc1Z0O7aQLJgB734dO2i56LLYDdI4gHYk2GAbQH2WI97hNeC7dj3fPEH8I9gV9"
+                "U323AXj1AJXbFPFIHGOTdC29QUUeH2SSc6NWhfQDDXd5Q5iXCKEAUGX3SKcNFIfVOYJgZCLjfHYQdgOQ"
+                "GCjKNgbEV7Hj34MU3b79iANX2DbMYfb9iGi78BWH2HYAd7IAhk7U0OYGHKJX1bIUUj1KBLhAUg46GaER"
+                "G9W3ARMfBCj6kSdDF9TdkWAjWTDj722IeVJERC4bKU2VDFG20kDhCMF985efD1SS8DfXcdCHF1kDUkSA"
+                "884FHYiFEPkaagQOBQaN9BNaEHNbbd002DCIIX5eMP4HgPJPF";
+   /* RADIX 64 */
+   char *gr64 = "2";
+   char *pr64 = "3//////////yaFsg8XQC8qnCPYYu3S7D4f0au8YcVCT08BlgOx4viYKKe8UOuq1DtlbHcppJf36p0h2c"
+                "toNnGtJ+4rRMrHmaNaXRLsObv+nlHCGkccD+rh2/zSjlG6j+tkE6lxMecVfQwV915yIn/cIIXcKUpaMp"
+                "t207oueME/1PZQI3OSLTEQQHO/gFqapr+3PLqZtAEjbXnYyrOWXLAxdjKf1t2Mbcrd33LEIhoO1F5qR0"
+                "ZA625yCf1UHYuspZlZddSi60w60vidWwBi1wAFjSLTy6zCKidUAylsbLWN63cLINpgbMhb5T8c69Zw1H"
+                "0LSevQYgogQF//////////";
+   char *xr64 = "2cQ1hSE6pfHCFUsQSm7SoSKO9Gu+ssBvMHcFZS05VTRxLwklruWPYn";
+   char *yr64 = "v16Ooo3H1ZVe7imaLEBOKqVjTktXS3xwZkOifMy3D1sg8sKKXGQ9fwBhh7TPKww0wLmKnZHANLCtq03g"
+                "CEP90+xZnOaaFRmt73a5BR+w826hwf8wVEYIEt0aqKcOzDE3e2TJskjkpRu2sWJw/V3A1k68WdbO4lUg"
+                "BZrzx/SFkjwstC4WecywWzQNDxdtv7D7mkcCl1jlfkdxm5BXB0jINodqCOFSqTIfadQIMb6jEKnimsVW"
+                "ktOLMDi2myguZBa66HKw8Xxj2FZAbeabUhBgPOWhD0wE3HUksSrvYCmgEwQfiWt113rpKMlD+wGeDgLl"
+                "fRyavw8/WlIpGdyZr922C";
+   /* RADIX 256 */
+   unsigned char gbin[] = { 0x02 };
+   unsigned char pbin[] = {
+      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+      0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+      0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+      0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+      0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+      0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+      0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+      0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+      0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+      0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+      0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+      0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+      0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+      0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+      0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+      0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+   };
+   unsigned char xbin[] = {
+      0xA6, 0x68, 0x1A, 0xDC, 0x38, 0x6C, 0xE9, 0x44, 0xC3, 0xDE, 0xD9, 0xA7, 0x30, 0x1D, 0xCC, 0x9C,
+      0x51, 0x82, 0x50, 0xE3, 0xED, 0xB6, 0x2F, 0x95, 0x91, 0x98, 0xF8, 0xDC, 0x00, 0x57, 0xDD, 0x6F,
+      0xB5, 0x7A, 0xBA, 0xFD, 0x78, 0x81, 0x98, 0xB1
+   };
+   unsigned char ybin[] = {
+      0x39, 0x04, 0x66, 0x32, 0xC8, 0x34, 0x41, 0x8D, 0xFA, 0x07, 0xB3, 0x09, 0x15, 0x38, 0xB6, 0x14,
+      0xD1, 0xFB, 0x5D, 0xBB, 0x78, 0x5C, 0x0F, 0xBE, 0xA3, 0xB9, 0x8B, 0x29, 0x5B, 0xC0, 0xCD, 0x07,
+      0x6A, 0x88, 0xD9, 0x45, 0x21, 0x41, 0xA2, 0x69, 0xE8, 0xBA, 0xEB, 0x1D, 0xD6, 0x54, 0xEB, 0xA0,
+      0x3A, 0x57, 0x05, 0x31, 0x8D, 0x12, 0x97, 0x54, 0xCD, 0xF4, 0x00, 0x3A, 0x8C, 0x39, 0x92, 0x40,
+      0xFB, 0xB8, 0xF1, 0x62, 0x49, 0x0F, 0x6F, 0x0D, 0xC7, 0x0E, 0x41, 0x4B, 0x6F, 0xEE, 0x88, 0x08,
+      0x6A, 0xFA, 0xA4, 0x8E, 0x9F, 0x3A, 0x24, 0x8E, 0xDC, 0x09, 0x34, 0x52, 0x66, 0x3D, 0x34, 0xE0,
+      0xE8, 0x09, 0xD4, 0xF6, 0xBA, 0xDB, 0xB3, 0x6F, 0x80, 0xB6, 0x81, 0x3E, 0xBF, 0x7C, 0x32, 0x81,
+      0xB8, 0x62, 0x20, 0x9E, 0x56, 0x04, 0xBD, 0xEA, 0x8B, 0x8F, 0x5F, 0x7B, 0xFD, 0xC3, 0xEE, 0xB7,
+      0xAD, 0xB7, 0x30, 0x48, 0x28, 0x9B, 0xCE, 0xA0, 0xF5, 0xA5, 0xCD, 0xEE, 0x7D, 0xF9, 0x1C, 0xD1,
+      0xF0, 0xBA, 0x63, 0x2F, 0x06, 0xDB, 0xE9, 0xBA, 0x7E, 0xF0, 0x14, 0xB8, 0x4B, 0x02, 0xD4, 0x97,
+      0xCA, 0x7D, 0x0C, 0x60, 0xF7, 0x34, 0x75, 0x2A, 0x64, 0x9D, 0xA4, 0x96, 0x94, 0x6B, 0x4E, 0x53,
+      0x1B, 0x30, 0xD9, 0xF8, 0x2E, 0xDD, 0x85, 0x56, 0x36, 0xC0, 0xB0, 0xF2, 0xAE, 0x23, 0x2E, 0x41,
+      0x86, 0x45, 0x4E, 0x88, 0x87, 0xBB, 0x42, 0x3E, 0x32, 0xA5, 0xA2, 0x49, 0x5E, 0xAC, 0xBA, 0x99,
+      0x62, 0x0A, 0xCD, 0x03, 0xA3, 0x83, 0x45, 0xEB, 0xB6, 0x73, 0x5E, 0x62, 0x33, 0x0A, 0x8E, 0xE9,
+      0xAA, 0x6C, 0x83, 0x70, 0x41, 0x0F, 0x5C, 0xD4, 0x5A, 0xF3, 0x7E, 0xE9, 0x0A, 0x0D, 0xA9, 0x5B,
+      0xE9, 0x6F, 0xC9, 0x39, 0xE8, 0x8F, 0xE0, 0xBD, 0x2C, 0xD0, 0x9F, 0xC8, 0xF5, 0x24, 0x20, 0x8C
+   };
+
+   struct {
+     int radix;
+     void* g; int glen;
+     void* p; int plen;
+     void* x; int xlen;
+     void* y; int ylen;
+   } test[4] = {
+      { 16,  ghex, strlen(ghex)+1, phex, strlen(phex)+1, xhex, strlen(xhex)+1, yhex, strlen(yhex)+1 },
+      { 47,  gr47, strlen(gr47)+1, pr47, strlen(pr47)+1, xr47, strlen(xr47)+1, yr47, strlen(yr47)+1 },
+      { 64,  gr64, strlen(gr64)+1, pr64, strlen(pr64)+1, xr64, strlen(xr64)+1, yr64, strlen(yr64)+1 },
+      { 256, gbin, sizeof(gbin),   pbin, sizeof(pbin),   xbin, sizeof(xbin),   ybin, sizeof(ybin)   }
+   };
+
+   unsigned char export_private[] = {
+      0x30, 0x82, 0x01, 0x3A, 0x02, 0x01, 0x00, 0x03, 0x02, 0x07, 0x80, 0x02, 0x82, 0x01, 0x01, 0x00,
+      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+      0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+      0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+      0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+      0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+      0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+      0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+      0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+      0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+      0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+      0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+      0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+      0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+      0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+      0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+      0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+      0x02, 0x01, 0x02, 0x02, 0x29, 0x00, 0xA6, 0x68, 0x1A, 0xDC, 0x38, 0x6C, 0xE9, 0x44, 0xC3, 0xDE,
+      0xD9, 0xA7, 0x30, 0x1D, 0xCC, 0x9C, 0x51, 0x82, 0x50, 0xE3, 0xED, 0xB6, 0x2F, 0x95, 0x91, 0x98,
+      0xF8, 0xDC, 0x00, 0x57, 0xDD, 0x6F, 0xB5, 0x7A, 0xBA, 0xFD, 0x78, 0x81, 0x98, 0xB1
+   };
+   unsigned char export_public[] = {
+      0x30, 0x82, 0x02, 0x13, 0x02, 0x01, 0x00, 0x03, 0x02, 0x07, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
+      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+      0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+      0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+      0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+      0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+      0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+      0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+      0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+      0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+      0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+      0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+      0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+      0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+      0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+      0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+      0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+      0x02, 0x01, 0x02, 0x02, 0x82, 0x01, 0x00, 0x39, 0x04, 0x66, 0x32, 0xC8, 0x34, 0x41, 0x8D, 0xFA,
+      0x07, 0xB3, 0x09, 0x15, 0x38, 0xB6, 0x14, 0xD1, 0xFB, 0x5D, 0xBB, 0x78, 0x5C, 0x0F, 0xBE, 0xA3,
+      0xB9, 0x8B, 0x29, 0x5B, 0xC0, 0xCD, 0x07, 0x6A, 0x88, 0xD9, 0x45, 0x21, 0x41, 0xA2, 0x69, 0xE8,
+      0xBA, 0xEB, 0x1D, 0xD6, 0x54, 0xEB, 0xA0, 0x3A, 0x57, 0x05, 0x31, 0x8D, 0x12, 0x97, 0x54, 0xCD,
+      0xF4, 0x00, 0x3A, 0x8C, 0x39, 0x92, 0x40, 0xFB, 0xB8, 0xF1, 0x62, 0x49, 0x0F, 0x6F, 0x0D, 0xC7,
+      0x0E, 0x41, 0x4B, 0x6F, 0xEE, 0x88, 0x08, 0x6A, 0xFA, 0xA4, 0x8E, 0x9F, 0x3A, 0x24, 0x8E, 0xDC,
+      0x09, 0x34, 0x52, 0x66, 0x3D, 0x34, 0xE0, 0xE8, 0x09, 0xD4, 0xF6, 0xBA, 0xDB, 0xB3, 0x6F, 0x80,
+      0xB6, 0x81, 0x3E, 0xBF, 0x7C, 0x32, 0x81, 0xB8, 0x62, 0x20, 0x9E, 0x56, 0x04, 0xBD, 0xEA, 0x8B,
+      0x8F, 0x5F, 0x7B, 0xFD, 0xC3, 0xEE, 0xB7, 0xAD, 0xB7, 0x30, 0x48, 0x28, 0x9B, 0xCE, 0xA0, 0xF5,
+      0xA5, 0xCD, 0xEE, 0x7D, 0xF9, 0x1C, 0xD1, 0xF0, 0xBA, 0x63, 0x2F, 0x06, 0xDB, 0xE9, 0xBA, 0x7E,
+      0xF0, 0x14, 0xB8, 0x4B, 0x02, 0xD4, 0x97, 0xCA, 0x7D, 0x0C, 0x60, 0xF7, 0x34, 0x75, 0x2A, 0x64,
+      0x9D, 0xA4, 0x96, 0x94, 0x6B, 0x4E, 0x53, 0x1B, 0x30, 0xD9, 0xF8, 0x2E, 0xDD, 0x85, 0x56, 0x36,
+      0xC0, 0xB0, 0xF2, 0xAE, 0x23, 0x2E, 0x41, 0x86, 0x45, 0x4E, 0x88, 0x87, 0xBB, 0x42, 0x3E, 0x32,
+      0xA5, 0xA2, 0x49, 0x5E, 0xAC, 0xBA, 0x99, 0x62, 0x0A, 0xCD, 0x03, 0xA3, 0x83, 0x45, 0xEB, 0xB6,
+      0x73, 0x5E, 0x62, 0x33, 0x0A, 0x8E, 0xE9, 0xAA, 0x6C, 0x83, 0x70, 0x41, 0x0F, 0x5C, 0xD4, 0x5A,
+      0xF3, 0x7E, 0xE9, 0x0A, 0x0D, 0xA9, 0x5B, 0xE9, 0x6F, 0xC9, 0x39, 0xE8, 0x8F, 0xE0, 0xBD, 0x2C,
+      0xD0, 0x9F, 0xC8, 0xF5, 0x24, 0x20, 0x8C
+   };
+   unsigned char key_parts[4][512];
+   unsigned long key_lens[4];
+
+   for (i = 0; i < 4; i++) {
+      for (j = 0; j < 4; ++j) {
+         key_lens[j] = sizeof(key_parts[j]);
+      }
+      if(test[i].radix != 256) {
+         DO(radix_to_bin(test[i].x, test[i].radix, key_parts[0], &key_lens[0]));
+         DO(radix_to_bin(test[i].y, test[i].radix, key_parts[1], &key_lens[1]));
+         DO(radix_to_bin(test[i].p, test[i].radix, key_parts[2], &key_lens[2]));
+         DO(radix_to_bin(test[i].g, test[i].radix, key_parts[3], &key_lens[3]));
+
+         DO(dh_set_pg(key_parts[2], key_lens[2], key_parts[3], key_lens[3], &k1));
+         DO(dh_set_key(NULL, 0, key_parts[0], key_lens[0], &k1));
+      }
+      else {
+         DO(dh_set_pg(test[i].p, test[i].plen, test[i].g, test[i].glen, &k1));
+         DO(dh_set_key(NULL, 0, test[i].x, test[i].xlen, &k1));
+      }
+
+      len = sizeof(buf);
+      DO(dh_export(buf, &len, PK_PRIVATE, &k1));
+      if (compare_testvector(buf, len, export_private, sizeof(export_private), "radix_test", i*10 + 0)) {
+         printf("radix_test: dh_export+PK_PRIVATE mismatch\n");
+         dh_free(&k1);
+         return CRYPT_ERROR;
+      }
+      len = sizeof(buf);
+      DO(dh_export(buf, &len, PK_PUBLIC, &k1));
+      if (compare_testvector(buf, len, export_public, sizeof(export_public), "radix_test", i*10 + 1)) {
+         printf("radix_test: dh_export+PK_PUBLIC mismatch\n");
+         dh_free(&k1);
+         return CRYPT_ERROR;
+      }
+      len = sizeof(buf);
+      DO(dh_export_key(buf, &len, PK_PRIVATE, &k1));
+      if (compare_testvector(buf, len, xbin, sizeof(xbin), "radix_test", i*10 + 2)) {
+         printf("radix_test: dh_export+PK_PRIVATE mismatch\n");
+         dh_free(&k1);
+         return CRYPT_ERROR;
+      }
+      len = sizeof(buf);
+      DO(dh_export_key(buf, &len, PK_PUBLIC, &k1));
+      if (compare_testvector(buf, len, ybin, sizeof(ybin), "radix_test", i*10 + 3)) {
+         printf("radix_test: dh_export+PK_PUBLIC mismatch\n");
+         dh_free(&k1);
+         return CRYPT_ERROR;
+      }
+      dh_free(&k1);
+
+      if(test[i].radix != 256) {
+         DO(dh_set_pg(key_parts[2], key_lens[2], key_parts[3], key_lens[3], &k2));
+         DO(dh_set_key(key_parts[1], key_lens[1], NULL, 0, &k2));
+      }
+      else {
+         DO(dh_set_pg(test[i].p, test[i].plen, test[i].g, test[i].glen, &k2));
+         DO(dh_set_key(test[i].y, test[i].ylen, NULL, 0, &k2));
+      }
+
+      len = sizeof(buf);
+      DO(dh_export(buf, &len, PK_PUBLIC, &k2));
+      if (compare_testvector(buf, len, export_public, sizeof(export_public), "radix_test", i*10 + 6)) {
+         printf("radix_test: dh_export+PK_PUBLIC mismatch\n");
+         dh_free(&k2);
+         return CRYPT_ERROR;
+      }
+      len = sizeof(buf);
+      DO(dh_export_key(buf, &len, PK_PUBLIC, &k2));
+      if (compare_testvector(buf, len, ybin, sizeof(ybin), "radix_test", i*10 + 7)) {
+         printf("radix_test: dh_export+PK_PUBLIC mismatch\n");
+         dh_free(&k2);
+         return CRYPT_ERROR;
+      }
+      dh_free(&k2);
+
+      if(test[i].radix != 256) {
+         DO(dh_set_pg(key_parts[2], key_lens[2], key_parts[3], key_lens[3], &k3));
+      }
+      else {
+         DO(dh_set_pg(test[i].p, test[i].plen, test[i].g, test[i].glen, &k3));
+      }
+
+      DO(dh_make_key(&yarrow_prng, find_prng("yarrow"), &k3));
+      len = mp_unsigned_bin_size(k3.prime);
+      DO(mp_to_unsigned_bin(k3.prime, buf));
+      if (compare_testvector(buf, len, pbin, sizeof(pbin), "radix_test", i*10 + 8)) {
+         printf("radix_test: dh_make_key_ex prime mismatch\n");
+         dh_free(&k3);
+         return CRYPT_ERROR;
+      }
+      len = mp_unsigned_bin_size(k3.base);
+      DO(mp_to_unsigned_bin(k3.base, buf));
+      if (compare_testvector(buf, len, gbin, sizeof(gbin), "radix_test", i*10 + 9)) {
+         printf("radix_test: dh_make_key_ex base mismatch\n");
+         dh_free(&k3);
+         return CRYPT_ERROR;
+      }
+      dh_free(&k3);
+   }
+
+   return CRYPT_OK;
+}
+
 static int _basic_test(void)
 static int _basic_test(void)
 {
 {
    unsigned char buf[3][4096];
    unsigned char buf[3][4096];
    unsigned long x, y, z;
    unsigned long x, y, z;
    int           size;
    int           size;
-   dh_key        usera, userb;
-
-   if (register_prng(&yarrow_desc) == -1) {
-      printf("Error registering yarrow PRNG\n");
-      return CRYPT_ERROR;
-   }
-   if (register_hash(&md5_desc) == -1) {
-      printf("Error registering md5 hash\n");
-      return CRYPT_ERROR;
-   }
+   dh_key        usera = LTC_DH_KEY_INITIALIZER;
+   dh_key        userb = LTC_DH_KEY_INITIALIZER;
 
 
    /* make up two keys */
    /* 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));
+   DO(dh_set_pg_groupsize(KEYSIZE/8, &usera));
+   DO(dh_make_key(&yarrow_prng, find_prng ("yarrow"), &usera));
+   DO(dh_set_pg_groupsize(KEYSIZE/8, &userb));
+   DO(dh_make_key(&yarrow_prng, find_prng ("yarrow"), &userb));
 
 
    /* make the shared secret */
    /* make the shared secret */
    x = KEYSIZE;
    x = KEYSIZE;
@@ -209,13 +474,15 @@ static int _basic_test(void)
    }
    }
 
 
    for (x = 0; ltc_dh_sets[x].size != 0; x++) {
    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));
+      DO(dh_set_pg_groupsize(ltc_dh_sets[x].size, &usera));
+      DO(dh_make_key(&yarrow_prng, find_prng ("yarrow"), &usera));
       size = dh_get_groupsize(&usera);
       size = dh_get_groupsize(&usera);
       dh_free(&usera);
       dh_free(&usera);
       if (size != ltc_dh_sets[x].size) {
       if (size != ltc_dh_sets[x].size) {
          fprintf(stderr, "dh_groupsize mismatch %d %d\n", 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_ERROR;
       }
       }
+      dh_free(&usera);
    }
    }
 
 
    return CRYPT_OK;
    return CRYPT_OK;
@@ -227,6 +494,7 @@ int dh_test(void)
    if (_prime_test() != CRYPT_OK) fails++;
    if (_prime_test() != CRYPT_OK) fails++;
    if (_basic_test() != CRYPT_OK) fails++;
    if (_basic_test() != CRYPT_OK) fails++;
    if (_dhparam_test() != CRYPT_OK) fails++;
    if (_dhparam_test() != CRYPT_OK) fails++;
+   if (_radix_test() != CRYPT_OK) fails++;
    return fails > 0 ? CRYPT_FAIL_TESTVECTOR : CRYPT_OK;
    return fails > 0 ? CRYPT_FAIL_TESTVECTOR : CRYPT_OK;
 }
 }