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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user