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