diff options
Diffstat (limited to 'src/ltc')
90 files changed, 1392 insertions, 406 deletions
diff --git a/src/ltc/ciphers/aes/aes.c b/src/ltc/ciphers/aes/aes.c index dd6f14e8..507d5c57 100644 --- a/src/ltc/ciphers/aes/aes.c +++ b/src/ltc/ciphers/aes/aes.c @@ -44,15 +44,6 @@ const struct ltc_cipher_descriptor rijndael_desc = NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -const struct ltc_cipher_descriptor aes_desc = -{ - "aes", - 6, - 16, 32, 16, 10, - SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_DONE, ECB_KS, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - #else #define SETUP rijndael_enc_setup @@ -69,15 +60,6 @@ const struct ltc_cipher_descriptor rijndael_enc_desc = NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -const struct ltc_cipher_descriptor aes_enc_desc = -{ - "aes", - 6, - 16, 32, 16, 10, - SETUP, ECB_ENC, NULL, NULL, ECB_DONE, ECB_KS, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - #endif #define LTC_AES_TAB_C @@ -114,6 +96,7 @@ static ulong32 setup_mix2(ulong32 temp) int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) { int i; + unsigned char *K; ulong32 temp, *rk; #ifndef ENCRYPT_ONLY ulong32 *rrk; @@ -130,6 +113,10 @@ int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *s } skey->rijndael.Nr = 10 + ((keylen/8)-2)*2; + K = (void*)((((size_t)&skey->rijndael.K[15]) >> 4) << 4); + skey->rijndael.eK = (ulong32*)K; + K += (60 * sizeof(ulong32)); + skey->rijndael.dK = (ulong32*)K; /* setup the forward key */ i = 0; @@ -741,4 +728,3 @@ int ECB_KS(int *keysize) } #endif - diff --git a/src/ltc/ciphers/aes/aes_desc.c b/src/ltc/ciphers/aes/aes_desc.c new file mode 100644 index 00000000..5b42d92b --- /dev/null +++ b/src/ltc/ciphers/aes/aes_desc.c @@ -0,0 +1,244 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* Auto-detection of AES implementation by Steffen Jaeckel */ +/** + @file aes_desc.c + Run-time detection of correct AES implementation +*/ + +#include "tomcrypt_private.h" + +#if defined(LTC_RIJNDAEL) + +#ifndef ENCRYPT_ONLY + +#define AES_SETUP aes_setup +#define AES_ENC aes_ecb_encrypt +#define AES_DEC aes_ecb_decrypt +#define AES_DONE aes_done +#define AES_TEST aes_test +#define AES_KS aes_keysize + +const struct ltc_cipher_descriptor aes_desc = +{ + "aes", + 6, + 16, 32, 16, 10, + AES_SETUP, AES_ENC, AES_DEC, AES_TEST, AES_DONE, AES_KS, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +#else + +#define AES_SETUP aes_enc_setup +#define AES_ENC aes_enc_ecb_encrypt +#define AES_DONE aes_enc_done +#define AES_KS aes_enc_keysize + +const struct ltc_cipher_descriptor aes_enc_desc = +{ + "aes", + 6, + 16, 32, 16, 10, + AES_SETUP, AES_ENC, NULL, NULL, AES_DONE, AES_KS, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +#endif + +/* Code partially borrowed from https://software.intel.com/content/www/us/en/develop/articles/intel-sha-extensions.html */ +#if defined(LTC_HAS_AES_NI) +static LTC_INLINE int s_aesni_is_supported(void) +{ + static int initialized = 0, is_supported = 0; + + if (initialized == 0) { + int a, b, c, d; + + /* Look for CPUID.1.0.ECX[25] + * EAX = 1, ECX = 0 + */ + a = 1; + c = 0; + + asm volatile ("cpuid" + :"=a"(a), "=b"(b), "=c"(c), "=d"(d) + :"a"(a), "c"(c) + ); + + is_supported = ((c >> 25) & 1); + initialized = 1; + } + + return is_supported; +} + +#ifndef ENCRYPT_ONLY +int aesni_is_supported(void) +{ + return s_aesni_is_supported(); +} +#endif +#endif + + /** + Initialize the AES (Rijndael) block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +int AES_SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ +#ifdef LTC_HAS_AES_NI + if (s_aesni_is_supported()) { + return aesni_setup(key, keylen, num_rounds, skey); + } +#endif + /* Last resort, software AES */ + return rijndael_setup(key, keylen, num_rounds, skey); +} + +/** + Encrypts a block of text with AES + @param pt The input plaintext (16 bytes) + @param ct The output ciphertext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int AES_ENC(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ +#ifdef LTC_HAS_AES_NI + if (s_aesni_is_supported()) { + return aesni_ecb_encrypt(pt, ct, skey); + } +#endif + return rijndael_ecb_encrypt(pt, ct, skey); +} + + +/** + Decrypts a block of text with AES + @param ct The input ciphertext (16 bytes) + @param pt The output plaintext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +int AES_DEC(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ +#ifdef LTC_HAS_AES_NI + if (s_aesni_is_supported()) { + return aesni_ecb_decrypt(ct, pt, skey); + } +#endif + return rijndael_ecb_decrypt(ct, pt, skey); +} + +/** + Performs a self-test of the AES block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int AES_TEST(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + int err; + static const struct { + int keylen; + unsigned char key[32], pt[16], ct[16]; + } tests[] = { + { 16, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, + 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a } + }, { + 24, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, + 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 } + }, { + 32, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, + 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 } + } + }; + + symmetric_key key; + unsigned char tmp[2][16]; + int i, y; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + zeromem(&key, sizeof(key)); + if ((err = aes_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { + return err; + } + + aes_ecb_encrypt(tests[i].pt, tmp[0], &key); + aes_ecb_decrypt(tmp[0], tmp[1], &key); + if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES Encrypt", i) || + compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES Decrypt", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 16; y++) tmp[0][y] = 0; + for (y = 0; y < 1000; y++) aes_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) aes_ecb_decrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; + #endif +} + + +/** Terminate the context + @param skey The scheduled key +*/ +void AES_DONE(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int AES_KS(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize < 24) { + *keysize = 16; + return CRYPT_OK; + } + if (*keysize < 32) { + *keysize = 24; + return CRYPT_OK; + } + *keysize = 32; + return CRYPT_OK; +} + +#endif + diff --git a/src/ltc/ciphers/aes/aesni.c b/src/ltc/ciphers/aes/aesni.c new file mode 100644 index 00000000..e730177a --- /dev/null +++ b/src/ltc/ciphers/aes/aesni.c @@ -0,0 +1,371 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +/* AES-NI implementation by Steffen Jaeckel */ +/** + @file aesni.c + Implementation of AES via the AES-NI instruction on x86_64 +*/ + +#include "tomcrypt_private.h" + +#if defined(LTC_HAS_AES_NI) + +const struct ltc_cipher_descriptor aesni_desc = +{ + "aes", + 6, + 16, 32, 16, 10, + aesni_setup, aesni_ecb_encrypt, aesni_ecb_decrypt, aesni_test, aesni_done, aesni_keysize, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +#include <emmintrin.h> +#include <smmintrin.h> +#include <wmmintrin.h> + +#define setup_mix(t, c) _mm_extract_epi32(_mm_aeskeygenassist_si128(t, 0), c) +#define temp_load(k) _mm_loadu_si128((__m128i*)(k)) +#define temp_update(t, k) _mm_insert_epi32(t, k, 3) +#define temp_invert(k) _mm_aesimc_si128(*((__m128i*)(k))) + + +static const ulong32 rcon[] = { + 0x01UL, 0x02UL, 0x04UL, 0x08UL, 0x10UL, 0x20UL, 0x40UL, 0x80UL, 0x1BUL, 0x36UL +}; + + /** + Initialize the AES (Rijndael) block cipher + @param key The symmetric key you wish to pass + @param keylen The key length in bytes + @param num_rounds The number of rounds desired (0 for default) + @param skey The key in as scheduled by this function. + @return CRYPT_OK if successful + */ +int aesni_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int i; + unsigned char *K; + __m128i temp; + ulong32 *rk; + ulong32 *rrk; + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(skey != NULL); + + if (keylen != 16 && keylen != 24 && keylen != 32) { + return CRYPT_INVALID_KEYSIZE; + } + + if (num_rounds != 0 && num_rounds != (keylen / 4 + 6)) { + return CRYPT_INVALID_ROUNDS; + } + + skey->rijndael.Nr = keylen / 4 + 6; + K = (void*)((((size_t)&skey->rijndael.K[15]) >> 4) << 4); + skey->rijndael.eK = (ulong32*)K; + K += (60 * sizeof(ulong32)); + skey->rijndael.dK = (ulong32*)K; + + /* setup the forward key */ + i = 0; + rk = skey->rijndael.eK; + LOAD32L(rk[0], key); + LOAD32L(rk[1], key + 4); + LOAD32L(rk[2], key + 8); + LOAD32L(rk[3], key + 12); + if (keylen == 16) { + temp = temp_load(key); + for (;;) { + rk[4] = rk[0] ^ setup_mix(temp, 3) ^ rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) { + break; + } + temp = temp_update(temp, rk[7]); + rk += 4; + } + } else if (keylen == 24) { + LOAD32L(rk[4], key + 16); + LOAD32L(rk[5], key + 20); + temp = temp_load(key + 8); + for (;;) { + rk[6] = rk[0] ^ setup_mix(temp, 3) ^ rcon[i]; + rk[7] = rk[1] ^ rk[6]; + rk[8] = rk[2] ^ rk[7]; + rk[9] = rk[3] ^ rk[8]; + if (++i == 8) { + break; + } + rk[10] = rk[4] ^ rk[9]; + rk[11] = rk[5] ^ rk[10]; + temp = temp_update(temp, rk[11]); + rk += 6; + } + } else if (keylen == 32) { + LOAD32L(rk[4], key + 16); + LOAD32L(rk[5], key + 20); + LOAD32L(rk[6], key + 24); + LOAD32L(rk[7], key + 28); + temp = temp_load(key + 16); + for (;;) { + rk[8] = rk[0] ^ setup_mix(temp, 3) ^ rcon[i]; + rk[9] = rk[1] ^ rk[8]; + rk[10] = rk[2] ^ rk[9]; + rk[11] = rk[3] ^ rk[10]; + if (++i == 7) { + break; + } + temp = temp_update(temp, rk[11]); + rk[12] = rk[4] ^ setup_mix(temp, 2); + rk[13] = rk[5] ^ rk[12]; + rk[14] = rk[6] ^ rk[13]; + rk[15] = rk[7] ^ rk[14]; + temp = temp_update(temp, rk[15]); + rk += 8; + } + } else { + /* this can't happen */ + /* coverity[dead_error_line] */ + return CRYPT_ERROR; + } + + /* setup the inverse key now */ + rk = skey->rijndael.dK; + rrk = skey->rijndael.eK + skey->rijndael.Nr * 4; + + /* apply the inverse MixColumn transform to all round keys but the first and the last: */ + /* copy first */ + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk = *rrk; + rk -= 3; + rrk -= 3; + + for (i = 1; i < skey->rijndael.Nr; i++) { + rrk -= 4; + rk += 4; + temp = temp_invert(rk); + *((__m128i*) rk) = temp_invert(rrk); + } + + /* copy last */ + rrk -= 4; + rk += 4; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk++ = *rrk++; + *rk = *rrk; + + return CRYPT_OK; +} + +/** + Encrypts a block of text with AES + @param pt The input plaintext (16 bytes) + @param ct The output ciphertext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#else +int aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +#endif +{ + int Nr, r; + const __m128i *skeys; + __m128i block; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + Nr = skey->rijndael.Nr; + + if (Nr < 2 || Nr > 16) return CRYPT_INVALID_ROUNDS; + + skeys = (__m128i*) skey->rijndael.eK; + block = _mm_loadu_si128((const __m128i*) (pt)); + + block = _mm_xor_si128(block, skeys[0]); + for (r = 1; r < Nr - 1; r += 2) { + block = _mm_aesenc_si128(block, skeys[r]); + block = _mm_aesenc_si128(block, skeys[r + 1]); + } + block = _mm_aesenc_si128(block, skeys[Nr - 1]); + block = _mm_aesenclast_si128(block, skeys[Nr]); + + _mm_storeu_si128((__m128i*) ct, block); + + return CRYPT_OK; +} + +#ifdef LTC_CLEAN_STACK +int aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey) +{ + int err = s_aesni_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2); + return err; +} +#endif + + +/** + Decrypts a block of text with AES + @param ct The input ciphertext (16 bytes) + @param pt The output plaintext (16 bytes) + @param skey The key as scheduled + @return CRYPT_OK if successful +*/ +#ifdef LTC_CLEAN_STACK +static int s_aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#else +int aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +#endif +{ + int Nr, r; + const __m128i *skeys; + __m128i block; + + LTC_ARGCHK(pt != NULL); + LTC_ARGCHK(ct != NULL); + LTC_ARGCHK(skey != NULL); + + Nr = skey->rijndael.Nr; + + if (Nr < 2 || Nr > 16) return CRYPT_INVALID_ROUNDS; + + skeys = (__m128i*) skey->rijndael.dK; + block = _mm_loadu_si128((const __m128i*) (ct)); + + block = _mm_xor_si128(block, skeys[0]); + for (r = 1; r < Nr - 1; r += 2) { + block = _mm_aesdec_si128(block, skeys[r]); + block = _mm_aesdec_si128(block, skeys[r + 1]); + } + block = _mm_aesdec_si128(block, skeys[Nr - 1]); + block = _mm_aesdeclast_si128(block, skeys[Nr]); + + _mm_storeu_si128((__m128i*) pt, block); + + return CRYPT_OK; +} + + +#ifdef LTC_CLEAN_STACK +int aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey) +{ + int err = s_aesni_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2); + return err; +} +#endif + +/** + Performs a self-test of the AES block cipher + @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled +*/ +int aesni_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + int err; + static const struct { + int keylen; + unsigned char key[32], pt[16], ct[16]; + } tests[] = { + { 16, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, + 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a } + }, { + 24, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0, + 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 } + }, { + 32, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, + 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 } + } + }; + + symmetric_key key; + unsigned char tmp[2][16]; + int i, y; + + for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) { + zeromem(&key, sizeof(key)); + if ((err = aesni_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) { + return err; + } + + aesni_ecb_encrypt(tests[i].pt, tmp[0], &key); + aesni_ecb_decrypt(tmp[0], tmp[1], &key); + if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES-NI Encrypt", i) || + compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES-NI Decrypt", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + + /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */ + for (y = 0; y < 16; y++) tmp[0][y] = 0; + for (y = 0; y < 1000; y++) aesni_ecb_encrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 1000; y++) aesni_ecb_decrypt(tmp[0], tmp[0], &key); + for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR; + } + return CRYPT_OK; + #endif +} + + +/** Terminate the context + @param skey The scheduled key +*/ +void aesni_done(symmetric_key *skey) +{ + LTC_UNUSED_PARAM(skey); +} + + +/** + Gets suitable key size + @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable. + @return CRYPT_OK if the input key size is acceptable. +*/ +int aesni_keysize(int *keysize) +{ + LTC_ARGCHK(keysize != NULL); + + if (*keysize < 16) { + return CRYPT_INVALID_KEYSIZE; + } + if (*keysize < 24) { + *keysize = 16; + return CRYPT_OK; + } + if (*keysize < 32) { + *keysize = 24; + return CRYPT_OK; + } + *keysize = 32; + return CRYPT_OK; +} + +#endif diff --git a/src/ltc/ciphers/camellia.c b/src/ltc/ciphers/camellia.c index 7f13f621..733e9639 100644 --- a/src/ltc/ciphers/camellia.c +++ b/src/ltc/ciphers/camellia.c @@ -621,6 +621,9 @@ int camellia_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symme int camellia_test(void) { +#ifndef LTC_TEST + return CRYPT_NOP; +#else static const struct { int keylen; unsigned char key[32], pt[16], ct[16]; @@ -697,6 +700,7 @@ int camellia_test(void) } } return CRYPT_OK; +#endif } void camellia_done(symmetric_key *skey) diff --git a/src/ltc/encauth/gcm/gcm_add_aad.c b/src/ltc/encauth/gcm/gcm_add_aad.c index 1e71639f..5c3793eb 100644 --- a/src/ltc/encauth/gcm/gcm_add_aad.c +++ b/src/ltc/encauth/gcm/gcm_add_aad.c @@ -83,7 +83,7 @@ int gcm_add_aad(gcm_state *gcm, x = 0; #ifdef LTC_FAST - if (gcm->buflen == 0) { + if (gcm->buflen == 0 && adatalen > 15) { for (x = 0; x < (adatalen & ~15); x += 16) { for (y = 0; y < 16; y += sizeof(LTC_FAST_TYPE)) { *(LTC_FAST_TYPE_PTR_CAST(&gcm->X[y])) ^= *(LTC_FAST_TYPE_PTR_CAST(&adata[x + y])); diff --git a/src/ltc/encauth/gcm/gcm_memory.c b/src/ltc/encauth/gcm/gcm_memory.c index e16f0b88..4da5d542 100644 --- a/src/ltc/encauth/gcm/gcm_memory.c +++ b/src/ltc/encauth/gcm/gcm_memory.c @@ -106,6 +106,7 @@ int gcm_memory( int cipher, err = CRYPT_INVALID_ARG; } LTC_ERR: + gcm_reset(gcm); XFREE(orig); return err; } diff --git a/src/ltc/headers/tomcrypt_cfg.h b/src/ltc/headers/tomcrypt_cfg.h index 994a084b..2a024aa4 100644 --- a/src/ltc/headers/tomcrypt_cfg.h +++ b/src/ltc/headers/tomcrypt_cfg.h @@ -3,7 +3,7 @@ /* This is the build config file. * - * With this you can setup what to inlcude/exclude automatically during any build. Just comment + * With this you can setup what to include/exclude automatically during any build. Just comment * out the line that #define's the word for the thing you want to remove. phew! */ @@ -91,6 +91,11 @@ LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2); #define ENDIAN_LITTLE #define ENDIAN_64BITWORD #define LTC_FAST + #if defined(__SSE4_1__) + #if __SSE4_1__ == 1 + #define LTC_AMD64_SSE4_1 + #endif + #endif #endif /* detect PPC32 */ @@ -295,6 +300,15 @@ typedef unsigned long ltc_mp_digit; #define LTC_ALIGN(n) #endif +/* Define `LTC_NO_NULL_TERMINATION_CHECK` in the user code + * before including `tomcrypt.h` to disable this functionality. + */ +#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(LTC_NO_NULL_TERMINATION_CHECK) +# define LTC_NULL_TERMINATED __attribute__((sentinel)) +#else +# define LTC_NULL_TERMINATED +#endif + #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 405) # define LTC_DEPRECATED(s) __attribute__((deprecated("replaced by " #s))) # define PRIVATE_LTC_DEPRECATED_PRAGMA(s) _Pragma(#s) diff --git a/src/ltc/headers/tomcrypt_cipher.h b/src/ltc/headers/tomcrypt_cipher.h index a3ba8f30..06e61247 100644 --- a/src/ltc/headers/tomcrypt_cipher.h +++ b/src/ltc/headers/tomcrypt_cipher.h @@ -35,8 +35,10 @@ struct saferp_key { #ifdef LTC_RIJNDAEL struct rijndael_key { - ulong32 eK[60], dK[60]; + ulong32 *eK; + ulong32 *dK; int Nr; + unsigned char K[(60 + 60 + 4) * sizeof(ulong32)]; }; #endif @@ -688,18 +690,19 @@ extern const struct ltc_cipher_descriptor safer_k64_desc, safer_k128_desc, safer #endif #ifdef LTC_RIJNDAEL - -/* make aes an alias */ -#define aes_setup rijndael_setup -#define aes_ecb_encrypt rijndael_ecb_encrypt -#define aes_ecb_decrypt rijndael_ecb_decrypt -#define aes_test rijndael_test -#define aes_done rijndael_done -#define aes_keysize rijndael_keysize - -#define aes_enc_setup rijndael_enc_setup -#define aes_enc_ecb_encrypt rijndael_enc_ecb_encrypt -#define aes_enc_keysize rijndael_enc_keysize +/* declare aes properly now */ +int aes_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int aes_test(void); +void aes_done(symmetric_key *skey); +int aes_keysize(int *keysize); +int aes_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int aes_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +void aes_enc_done(symmetric_key *skey); +int aes_enc_keysize(int *keysize); +extern const struct ltc_cipher_descriptor aes_desc; +extern const struct ltc_cipher_descriptor aes_enc_desc; int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); @@ -711,8 +714,19 @@ int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, sym int rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); void rijndael_enc_done(symmetric_key *skey); int rijndael_enc_keysize(int *keysize); -extern const struct ltc_cipher_descriptor rijndael_desc, aes_desc; -extern const struct ltc_cipher_descriptor rijndael_enc_desc, aes_enc_desc; +extern const struct ltc_cipher_descriptor rijndael_desc; +extern const struct ltc_cipher_descriptor rijndael_enc_desc; +#endif + +#if defined(LTC_AES_NI) && defined(LTC_AMD64_SSE4_1) +int aesni_is_supported(void); +int aesni_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey); +int aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey); +int aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey); +int aesni_test(void); +void aesni_done(symmetric_key *skey); +int aesni_keysize(int *keysize); +extern const struct ltc_cipher_descriptor aesni_desc; #endif #ifdef LTC_XTEA diff --git a/src/ltc/headers/tomcrypt_custom.h b/src/ltc/headers/tomcrypt_custom.h index b13c2e08..f0a65fef 100644 --- a/src/ltc/headers/tomcrypt_custom.h +++ b/src/ltc/headers/tomcrypt_custom.h @@ -114,7 +114,7 @@ #define LTC_NO_MISC #define LTC_BASE64 -#endif +#endif /* LTC_EASY */ /* The minimal set of functionality to run the tests */ #ifdef LTC_MINIMAL @@ -129,7 +129,7 @@ #define LTC_TRY_URANDOM_FIRST #undef LTC_NO_FILE -#endif +#endif /* LTC_MINIMAL */ /* Enable self-test test vector checking */ #ifndef LTC_NO_TEST @@ -179,6 +179,7 @@ #define LTC_RC6 #define LTC_SAFERP #define LTC_RIJNDAEL +#define LTC_AES_NI #define LTC_XTEA /* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */ @@ -357,7 +358,7 @@ #define LTC_YARROW_AES 2 #endif -#endif +#endif /* LTC_YARROW */ #ifdef LTC_FORTUNA @@ -553,7 +554,7 @@ #define LTC_ECC_SECP384R1 #define LTC_ECC_SECP521R1 #endif -#endif +#endif /* LTC_MECC */ #if defined(LTC_DER) #ifndef LTC_DER_MAX_RECURSION @@ -690,15 +691,13 @@ #define LTC_MUTEX_UNLOCK(x) #define LTC_MUTEX_DESTROY(x) -#endif +#endif /* LTC_PTHREAD */ /* Debuggers */ /* define this if you use Valgrind, note: it CHANGES the way SOBER-128 and RC4 work (see the code) */ /* #define LTC_VALGRIND */ -#endif - #ifndef LTC_NO_FILE /* buffer size for reading from a file via fread(..) */ #ifndef LTC_FILE_READ_BUFSIZE @@ -739,3 +738,5 @@ #define LTC_ECC_SECP521R1 #undef LTC_ECC521 #endif + +#endif /* TOMCRYPT_CUSTOM_H_ */ diff --git a/src/ltc/headers/tomcrypt_hash.h b/src/ltc/headers/tomcrypt_hash.h index 4eb07126..3c4bcf5a 100644 --- a/src/ltc/headers/tomcrypt_hash.h +++ b/src/ltc/headers/tomcrypt_hash.h @@ -494,7 +494,8 @@ int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...); + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; #ifndef LTC_NO_FILE int hash_filehandle(int hash, FILE *in, unsigned char *out, unsigned long *outlen); diff --git a/src/ltc/headers/tomcrypt_mac.h b/src/ltc/headers/tomcrypt_mac.h index 549903c2..c8f4a322 100644 --- a/src/ltc/headers/tomcrypt_mac.h +++ b/src/ltc/headers/tomcrypt_mac.h @@ -19,7 +19,8 @@ int hmac_memory(int hash, int hmac_memory_multi(int hash, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...); + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; int hmac_file(int hash, const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen); @@ -47,7 +48,8 @@ int omac_memory(int cipher, int omac_memory_multi(int cipher, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...); + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; int omac_file(int cipher, const unsigned char *key, unsigned long keylen, const char *filename, @@ -83,7 +85,8 @@ int pmac_memory(int cipher, int pmac_memory_multi(int cipher, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...); + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; int pmac_file(int cipher, const unsigned char *key, unsigned long keylen, @@ -112,7 +115,10 @@ int poly1305_init(poly1305_state *st, const unsigned char *key, unsigned long ke int poly1305_process(poly1305_state *st, const unsigned char *in, unsigned long inlen); int poly1305_done(poly1305_state *st, unsigned char *mac, unsigned long *maclen); int poly1305_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen); -int poly1305_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...); +int poly1305_memory_multi(const unsigned char *key, unsigned long keylen, + unsigned char *mac, unsigned long *maclen, + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; int poly1305_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen); int poly1305_test(void); #endif /* LTC_POLY1305 */ @@ -123,7 +129,10 @@ int blake2smac_init(blake2smac_state *st, unsigned long outlen, const unsigned c int blake2smac_process(blake2smac_state *st, const unsigned char *in, unsigned long inlen); int blake2smac_done(blake2smac_state *st, unsigned char *mac, unsigned long *maclen); int blake2smac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen); -int blake2smac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...); +int blake2smac_memory_multi(const unsigned char *key, unsigned long keylen, + unsigned char *mac, unsigned long *maclen, + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; int blake2smac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen); int blake2smac_test(void); #endif /* LTC_BLAKE2SMAC */ @@ -134,7 +143,10 @@ int blake2bmac_init(blake2bmac_state *st, unsigned long outlen, const unsigned c int blake2bmac_process(blake2bmac_state *st, const unsigned char *in, unsigned long inlen); int blake2bmac_done(blake2bmac_state *st, unsigned char *mac, unsigned long *maclen); int blake2bmac_memory(const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *mac, unsigned long *maclen); -int blake2bmac_memory_multi(const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen, const unsigned char *in, unsigned long inlen, ...); +int blake2bmac_memory_multi(const unsigned char *key, unsigned long keylen, + unsigned char *mac, unsigned long *maclen, + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; int blake2bmac_file(const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *mac, unsigned long *maclen); int blake2bmac_test(void); #endif /* LTC_BLAKE2BMAC */ @@ -186,7 +198,8 @@ int xcbc_memory(int cipher, int xcbc_memory_multi(int cipher, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...); + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; int xcbc_file(int cipher, const unsigned char *key, unsigned long keylen, const char *filename, @@ -220,7 +233,8 @@ int f9_memory(int cipher, int f9_memory_multi(int cipher, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, - const unsigned char *in, unsigned long inlen, ...); + const unsigned char *in, unsigned long inlen, ...) + LTC_NULL_TERMINATED; int f9_file(int cipher, const unsigned char *key, unsigned long keylen, const char *fname, diff --git a/src/ltc/headers/tomcrypt_macros.h b/src/ltc/headers/tomcrypt_macros.h index 94aa7c32..257f5238 100644 --- a/src/ltc/headers/tomcrypt_macros.h +++ b/src/ltc/headers/tomcrypt_macros.h @@ -1,6 +1,11 @@ /* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ + +#define LTC_TMPVAR__(n, l) n ## l +#define LTC_TMPVAR_(n, l) LTC_TMPVAR__(n, l) +#define LTC_TMPVAR(n) LTC_TMPVAR_(LTC_ ## n ## _, __LINE__) + /* ---- HELPER MACROS ---- */ #ifdef ENDIAN_NEUTRAL @@ -275,20 +280,20 @@ static inline ulong32 ROR(ulong32 word, int i) #ifndef LTC_NO_ROLC #define ROLc(word,i) ({ \ - ulong32 ROLc_tmp = (word); \ + ulong32 LTC_TMPVAR(ROLc) = (word); \ __asm__ ("roll %2, %0" : \ - "=r" (ROLc_tmp) : \ - "0" (ROLc_tmp), \ + "=r" (LTC_TMPVAR(ROLc)) : \ + "0" (LTC_TMPVAR(ROLc)), \ "I" (i)); \ - ROLc_tmp; \ + LTC_TMPVAR(ROLc); \ }) #define RORc(word,i) ({ \ - ulong32 RORc_tmp = (word); \ + ulong32 LTC_TMPVAR(RORc) = (word); \ __asm__ ("rorl %2, %0" : \ - "=r" (RORc_tmp) : \ - "0" (RORc_tmp), \ + "=r" (LTC_TMPVAR(RORc)) : \ + "0" (LTC_TMPVAR(RORc)), \ "I" (i)); \ - RORc_tmp; \ + LTC_TMPVAR(RORc); \ }) #else @@ -393,20 +398,20 @@ static inline ulong64 ROR64(ulong64 word, int i) #ifndef LTC_NO_ROLC #define ROL64c(word,i) ({ \ - ulong64 ROL64c_tmp = word; \ + ulong64 LTC_TMPVAR(ROL64c) = word; \ __asm__ ("rolq %2, %0" : \ - "=r" (ROL64c_tmp) : \ - "0" (ROL64c_tmp), \ + "=r" (LTC_TMPVAR(ROL64c)) : \ + "0" (LTC_TMPVAR(ROL64c)), \ "J" (i)); \ - ROL64c_tmp; \ + LTC_TMPVAR(ROL64c); \ }) #define ROR64c(word,i) ({ \ - ulong64 ROR64c_tmp = word; \ + ulong64 LTC_TMPVAR(ROR64c) = word; \ __asm__ ("rorq %2, %0" : \ - "=r" (ROR64c_tmp) : \ - "0" (ROR64c_tmp), \ + "=r" (LTC_TMPVAR(ROR64c)) : \ + "0" (LTC_TMPVAR(ROR64c)), \ "J" (i)); \ - ROR64c_tmp; \ + LTC_TMPVAR(ROR64c); \ }) #else /* LTC_NO_ROLC */ diff --git a/src/ltc/headers/tomcrypt_math.h b/src/ltc/headers/tomcrypt_math.h index bb49915f..b7dedf6b 100644 --- a/src/ltc/headers/tomcrypt_math.h +++ b/src/ltc/headers/tomcrypt_math.h @@ -502,9 +502,9 @@ typedef struct { extern ltc_math_descriptor ltc_mp; -int ltc_init_multi(void **a, ...); -void ltc_deinit_multi(void *a, ...); -void ltc_cleanup_multi(void **a, ...); +int ltc_init_multi(void **a, ...) LTC_NULL_TERMINATED; +void ltc_deinit_multi(void *a, ...) LTC_NULL_TERMINATED; +void ltc_cleanup_multi(void **a, ...) LTC_NULL_TERMINATED; #ifdef LTM_DESC extern const ltc_math_descriptor ltm_desc; diff --git a/src/ltc/headers/tomcrypt_misc.h b/src/ltc/headers/tomcrypt_misc.h index ae861fe3..3a2b7b12 100644 --- a/src/ltc/headers/tomcrypt_misc.h +++ b/src/ltc/headers/tomcrypt_misc.h @@ -93,7 +93,7 @@ const char *error_to_string(int err); extern const char *crypt_build_settings; /* ---- HMM ---- */ -int crypt_fsa(void *mp, ...); +int crypt_fsa(void *mp, ...) LTC_NULL_TERMINATED; /* ---- Dynamic language support ---- */ int crypt_get_constant(const char* namein, int *valueout); @@ -146,6 +146,7 @@ enum padding_type { LTC_PAD_ISO_10126 = 0x1000U, #endif LTC_PAD_ANSI_X923 = 0x2000U, + LTC_PAD_SSH = 0x3000U, /* The following padding modes don't contain the padding * length as last byte of the padding. */ @@ -171,8 +172,8 @@ typedef enum ssh_data_type_ { } ssh_data_type; /* VA list handy helpers with tuples of <type, data> */ -int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...); -int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...); +int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) LTC_NULL_TERMINATED; +int ssh_decode_sequence_multi(const unsigned char *in, unsigned long *inlen, ...) LTC_NULL_TERMINATED; #endif /* LTC_SSH */ int compare_testvector(const void* is, const unsigned long is_len, const void* should, const unsigned long should_len, const char* what, int which); diff --git a/src/ltc/headers/tomcrypt_pk.h b/src/ltc/headers/tomcrypt_pk.h index 167789e4..903e118d 100644 --- a/src/ltc/headers/tomcrypt_pk.h +++ b/src/ltc/headers/tomcrypt_pk.h @@ -355,13 +355,31 @@ int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, curve25519_key *key); -int ed25519_sign(const unsigned char *msg, unsigned long msglen, - unsigned char *sig, unsigned long *siglen, +int ed25519_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, const curve25519_key *private_key); - +int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + const curve25519_key *private_key); +int ed25519ph_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + const curve25519_key *private_key); int ed25519_verify(const unsigned char *msg, unsigned long msglen, const unsigned char *sig, unsigned long siglen, - int *stat, const curve25519_key *public_key); + int *stat, + const curve25519_key *public_key); +int ed25519ctx_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const curve25519_key *public_key); +int ed25519ph_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const curve25519_key *public_key); /** X25519 Key-Exchange API */ int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key); @@ -530,43 +548,43 @@ typedef struct ltc_asn1_list_ { struct ltc_asn1_list_ *prev, *next, *child, *parent; } ltc_asn1_list; -#define LTC_SET_ASN1(list, index, Type, Data, Size) \ - do { \ - int LTC_MACRO_temp = (index); \ - ltc_asn1_list *LTC_MACRO_list = (list); \ - LTC_MACRO_list[LTC_MACRO_temp].type = (Type); \ - LTC_MACRO_list[LTC_MACRO_temp].data = (void*)(Data); \ - LTC_MACRO_list[LTC_MACRO_temp].size = (Size); \ - LTC_MACRO_list[LTC_MACRO_temp].used = 0; \ - LTC_MACRO_list[LTC_MACRO_temp].optional = 0; \ - LTC_MACRO_list[LTC_MACRO_temp].klass = 0; \ - LTC_MACRO_list[LTC_MACRO_temp].pc = 0; \ - LTC_MACRO_list[LTC_MACRO_temp].tag = 0; \ +#define LTC_SET_ASN1(list, index, Type, Data, Size) \ + do { \ + int LTC_TMPVAR(SA) = (index); \ + ltc_asn1_list *LTC_TMPVAR(SA_list) = (list); \ + LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].type = (Type); \ + LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].data = (void*)(Data); \ + LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].size = (Size); \ + LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].used = 0; \ + LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].optional = 0; \ + LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].klass = 0; \ + LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].pc = 0; \ + LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].tag = 0; \ } while (0) -#define LTC_SET_ASN1_IDENTIFIER(list, index, Class, Pc, Tag) \ - do { \ - int LTC_MACRO_temp = (index); \ - ltc_asn1_list *LTC_MACRO_list = (list); \ - LTC_MACRO_list[LTC_MACRO_temp].type = LTC_ASN1_CUSTOM_TYPE; \ - LTC_MACRO_list[LTC_MACRO_temp].klass = (Class); \ - LTC_MACRO_list[LTC_MACRO_temp].pc = (Pc); \ - LTC_MACRO_list[LTC_MACRO_temp].tag = (Tag); \ +#define LTC_SET_ASN1_IDENTIFIER(list, index, Class, Pc, Tag) \ + do { \ + int LTC_TMPVAR(SAI) = (index); \ + ltc_asn1_list *LTC_TMPVAR(SAI_list) = (list); \ + LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].type = LTC_ASN1_CUSTOM_TYPE; \ + LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].klass = (Class); \ + LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].pc = (Pc); \ + LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].tag = (Tag); \ } while (0) -#define LTC_SET_ASN1_CUSTOM_CONSTRUCTED(list, index, Class, Tag, Data) \ - do { \ - int LTC_MACRO_temp##__LINE__ = (index); \ - LTC_SET_ASN1(list, LTC_MACRO_temp##__LINE__, LTC_ASN1_CUSTOM_TYPE, Data, 1); \ - LTC_SET_ASN1_IDENTIFIER(list, LTC_MACRO_temp##__LINE__, Class, LTC_ASN1_PC_CONSTRUCTED, Tag); \ +#define LTC_SET_ASN1_CUSTOM_CONSTRUCTED(list, index, Class, Tag, Data) \ + do { \ + int LTC_TMPVAR(SACC) = (index); \ + LTC_SET_ASN1(list, LTC_TMPVAR(SACC), LTC_ASN1_CUSTOM_TYPE, Data, 1); \ + LTC_SET_ASN1_IDENTIFIER(list, LTC_TMPVAR(SACC), Class, LTC_ASN1_PC_CONSTRUCTED, Tag); \ } while (0) -#define LTC_SET_ASN1_CUSTOM_PRIMITIVE(list, index, Class, Tag, Type, Data, Size) \ - do { \ - int LTC_MACRO_temp##__LINE__ = (index); \ - LTC_SET_ASN1(list, LTC_MACRO_temp##__LINE__, LTC_ASN1_CUSTOM_TYPE, Data, Size); \ - LTC_SET_ASN1_IDENTIFIER(list, LTC_MACRO_temp##__LINE__, Class, LTC_ASN1_PC_PRIMITIVE, Tag); \ - list[LTC_MACRO_temp##__LINE__].used = (int)(Type); \ +#define LTC_SET_ASN1_CUSTOM_PRIMITIVE(list, index, Class, Tag, Type, Data, Size) \ + do { \ + int LTC_TMPVAR(SACP) = (index); \ + LTC_SET_ASN1(list, LTC_TMPVAR(SACP), LTC_ASN1_CUSTOM_TYPE, Data, Size); \ + LTC_SET_ASN1_IDENTIFIER(list, LTC_TMPVAR(SACP), Class, LTC_ASN1_PC_PRIMITIVE, Tag); \ + list[LTC_TMPVAR(SACP)].used = (int)(Type); \ } while (0) extern const char* der_asn1_class_to_string_map[]; @@ -636,8 +654,8 @@ int der_encode_setof(const ltc_asn1_list *list, unsigned long inlen, unsigned char *out, unsigned long *outlen); /* VA list handy helpers with triplets of <type, size, data> */ -int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...); -int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...); +int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) LTC_NULL_TERMINATED; +int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) LTC_NULL_TERMINATED; /* FLEXI DECODER handle unknown list decoder */ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out); diff --git a/src/ltc/headers/tomcrypt_private.h b/src/ltc/headers/tomcrypt_private.h index 7c1e1724..aa251e2a 100644 --- a/src/ltc/headers/tomcrypt_private.h +++ b/src/ltc/headers/tomcrypt_private.h @@ -9,17 +9,25 @@ #define LTC_PAD_MASK (0xF000U) +/* `NULL` as defined by the standard is not guaranteed to be of a pointer + * type. In order to make sure that in vararg API's a pointer type is used, + * define our own version and use that one internally. + */ +#ifndef LTC_NULL + #define LTC_NULL ((void *)0) +#endif + /* * Internal Enums */ enum ltc_oid_id { - PKA_RSA, - PKA_DSA, - PKA_EC, - PKA_EC_PRIMEF, - PKA_X25519, - PKA_ED25519, + LTC_OID_RSA, + LTC_OID_DSA, + LTC_OID_EC, + LTC_OID_EC_PRIMEF, + LTC_OID_X25519, + LTC_OID_ED25519, }; /* @@ -69,6 +77,10 @@ typedef struct /* tomcrypt_cipher.h */ +#if defined(LTC_AES_NI) && defined(LTC_AMD64_SSE4_1) +#define LTC_HAS_AES_NI +#endif + void blowfish_enc(ulong32 *data, unsigned long blocks, const symmetric_key *skey); int blowfish_expand(const unsigned char *key, int keylen, const unsigned char *data, int datalen, @@ -90,7 +102,8 @@ int func_name (hash_state * md, const unsigned char *in, unsigned long inlen) if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \ return CRYPT_INVALID_ARG; \ } \ - if ((md-> state_var .length + inlen * 8) < md-> state_var .length) { \ + if (((md-> state_var .length + inlen * 8) < md-> state_var .length) \ + || ((inlen * 8) < inlen)) { \ return CRYPT_HASH_OVERFLOW; \ } \ while (inlen > 0) { \ @@ -202,6 +215,17 @@ void ocb3_int_xor_blocks(unsigned char *out, const unsigned char *block_a, const /* tomcrypt_misc.h */ +typedef enum { + /** Use `\r\n` as line separator */ + BASE64_PEM_CRLF = 1, + /** Create output with 72 chars line length */ + BASE64_PEM_SSH = 2, +} base64_pem_flags; + +int base64_encode_pem(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + unsigned int flags); + void copy_or_zeromem(const unsigned char* src, unsigned char* dest, unsigned long len, int coz); int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *dec_size); @@ -225,6 +249,7 @@ int rsa_init(rsa_key *key); void rsa_shrink_key(rsa_key *key); int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e, rsa_key *key); /* used by op-tee */ +int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key); #endif /* LTC_MRSA */ /* ---- DH Routines ---- */ @@ -318,16 +343,19 @@ int dsa_int_validate_primes(const dsa_key *key, int *stat); int tweetnacl_crypto_sign( unsigned char *sm,unsigned long long *smlen, const unsigned char *m,unsigned long long mlen, - const unsigned char *sk, const unsigned char *pk); + const unsigned char *sk,const unsigned char *pk, + const unsigned char *ctx,unsigned long long cs); int tweetnacl_crypto_sign_open( int *stat, unsigned char *m,unsigned long long *mlen, const unsigned char *sm,unsigned long long smlen, + const unsigned char *ctx, unsigned long long cs, const unsigned char *pk); int tweetnacl_crypto_sign_keypair(prng_state *prng, int wprng, unsigned char *pk,unsigned char *sk); int tweetnacl_crypto_sk_to_pk(unsigned char *pk, const unsigned char *sk); int tweetnacl_crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p); int tweetnacl_crypto_scalarmult_base(unsigned char *q,const unsigned char *n); +int tweetnacl_crypto_ph(unsigned char *out, const unsigned char *msg, unsigned long long msglen); typedef int (*sk_to_pk)(unsigned char *pk ,const unsigned char *sk); int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen, @@ -337,6 +365,9 @@ int ec25519_import_pkcs8(const unsigned char *in, unsigned long inlen, int ec25519_export( unsigned char *out, unsigned long *outlen, int which, const curve25519_key *key); +int ec25519_crypto_ctx( unsigned char *out, unsigned long *outlen, + unsigned char flag, + const unsigned char *ctx, unsigned long ctxlen); #endif /* LTC_CURVE25519 */ #ifdef LTC_DER @@ -365,7 +396,8 @@ extern const unsigned long der_asn1_tag_to_type_map_sz; extern const int der_asn1_type_to_identifier_map[]; extern const unsigned long der_asn1_type_to_identifier_map_sz; -int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...); +int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...) + LTC_NULL_TERMINATED; int der_teletex_char_encode(int c); int der_teletex_value_decode(int v); diff --git a/src/ltc/math/fp/ltc_ecc_fp_mulmod.c b/src/ltc/math/fp/ltc_ecc_fp_mulmod.c index 180b1e2c..5827bf3b 100644 --- a/src/ltc/math/fp/ltc_ecc_fp_mulmod.c +++ b/src/ltc/math/fp/ltc_ecc_fp_mulmod.c @@ -1544,7 +1544,7 @@ int ltc_ecc_fp_restore_state(unsigned char *in, unsigned long inlen) goto ERR_OUT; } fp_cache[i].LUT[x] = p; - if ((err = mp_init_multi(&p->x, &p->y, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&p->x, &p->y, LTC_NULL)) != CRYPT_OK) { goto ERR_OUT; } p->z = NULL; diff --git a/src/ltc/misc/base64/base64_encode.c b/src/ltc/misc/base64/base64_encode.c index ad512d83..ef8aee90 100644 --- a/src/ltc/misc/base64/base64_encode.c +++ b/src/ltc/misc/base64/base64_encode.c @@ -21,23 +21,45 @@ static const char * const codes_base64url = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; #endif /* LTC_BASE64_URL */ -static int s_base64_encode_internal(const unsigned char *in, unsigned long inlen, - char *out, unsigned long *outlen, - const char *codes, int pad) +enum mode { + nopad = 0, + pad = 1, + lf = 2, + cr = 4, + ssh = 8, + crlf = lf | cr, +}; + +static int s_base64_encode_internal(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + const char *codes, unsigned int mode) { - unsigned long i, len2, leven; + unsigned long i, len2, leven, linelen; char *p; - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); + linelen = (mode & ssh) ? 72 : 64; + /* valid output size ? */ len2 = 4 * ((inlen + 2) / 3); + if ((mode & crlf) == lf) { + len2 += len2 / linelen; + } else if ((mode & crlf) == crlf) { + len2 += (len2 / linelen) * 2; + } if (*outlen < len2 + 1) { *outlen = len2 + 1; return CRYPT_BUFFER_OVERFLOW; } + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + + if ((void*)in == out) { + return CRYPT_INVALID_ARG; + } + p = out; leven = 3*(inlen / 3); for (i = 0; i < leven; i += 3) { @@ -46,6 +68,10 @@ static int s_base64_encode_internal(const unsigned char *in, unsigned long inle *p++ = codes[(((in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F]; *p++ = codes[in[2] & 0x3F]; in += 3; + if ((p - out) % linelen == 0) { + if (mode & cr) *p++ = '\r'; + if (mode & lf) *p++ = '\n'; + } } /* Pad it if necessary... */ if (i < inlen) { @@ -54,7 +80,7 @@ static int s_base64_encode_internal(const unsigned char *in, unsigned long inle *p++ = codes[(a >> 2) & 0x3F]; *p++ = codes[(((a & 3) << 4) + (b >> 4)) & 0x3F]; - if (pad) { + if (mode & pad) { *p++ = (i+1 < inlen) ? codes[(((b & 0xf) << 2)) & 0x3F] : '='; *p++ = '='; } @@ -83,7 +109,26 @@ static int s_base64_encode_internal(const unsigned char *in, unsigned long inle int base64_encode(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen) { - return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, 1); + return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, pad); +} + +/** + base64 Encode a buffer for PEM output + (NUL terminated with line-break at 64 chars) + @param in The input buffer to encode + @param inlen The length of the input buffer + @param out [out] The destination of the base64 encoded data + @param outlen [in/out] The max size and resulting size + @param flags \ref base64_pem_flags + @return CRYPT_OK if successful +*/ +int base64_encode_pem(const unsigned char *in, unsigned long inlen, + char *out, unsigned long *outlen, + unsigned int flags) +{ + int use_crlf = flags & BASE64_PEM_CRLF ? pad | crlf : pad | lf; + int ssh_style = flags & BASE64_PEM_SSH ? ssh : 0; + return s_base64_encode_internal(in, inlen, out, outlen, codes_base64, ssh_style | use_crlf); } #endif /* LTC_BASE64 */ @@ -100,13 +145,13 @@ int base64_encode(const unsigned char *in, unsigned long inlen, int base64url_encode(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen) { - return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, 0); + return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, nopad); } int base64url_strict_encode(const unsigned char *in, unsigned long inlen, char *out, unsigned long *outlen) { - return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, 1); + return s_base64_encode_internal(in, inlen, out, outlen, codes_base64url, pad); } #endif /* LTC_BASE64_URL */ diff --git a/src/ltc/misc/bcrypt/bcrypt.c b/src/ltc/misc/bcrypt/bcrypt.c index e1974f6a..1bebdffa 100644 --- a/src/ltc/misc/bcrypt/bcrypt.c +++ b/src/ltc/misc/bcrypt/bcrypt.c @@ -139,7 +139,7 @@ int bcrypt_pbkdf_openbsd(const void *secret, unsigned long secret_len, if ((err = hash_memory_multi(hash_idx, buf[0], &x, salt, salt_len, blkbuf, 4uL, - NULL, 0)) != CRYPT_OK) { + LTC_NULL)) != CRYPT_OK) { goto LBL_ERR; } y = MAXBLOCKSIZE; diff --git a/src/ltc/misc/crypt/crypt.c b/src/ltc/misc/crypt/crypt.c index 14576fa7..460cd59d 100644 --- a/src/ltc/misc/crypt/crypt.c +++ b/src/ltc/misc/crypt/crypt.c @@ -416,6 +416,9 @@ const char *crypt_build_settings = #if defined(LTC_ADLER32) " ADLER32 " #endif +#if defined(LTC_AES_NI) && defined(LTC_AMD64_SSE4_1) + " AES-NI " +#endif #if defined(LTC_BASE64) " BASE64 " #endif diff --git a/src/ltc/misc/crypt/crypt_register_all_ciphers.c b/src/ltc/misc/crypt/crypt_register_all_ciphers.c index bb2b873e..bfed2e68 100644 --- a/src/ltc/misc/crypt/crypt_register_all_ciphers.c +++ b/src/ltc/misc/crypt/crypt_register_all_ciphers.c @@ -16,6 +16,7 @@ int register_all_ciphers(void) { #ifdef LTC_RIJNDAEL + /* `aesni_desc` is explicitely not registered, since it's handled from within the `aes_desc` */ #ifdef ENCRYPT_ONLY /* alternative would be * register_cipher(&rijndael_enc_desc); diff --git a/src/ltc/misc/padding/padding_depad.c b/src/ltc/misc/padding/padding_depad.c index 7489de12..e3f71511 100644 --- a/src/ltc/misc/padding/padding_depad.c +++ b/src/ltc/misc/padding/padding_depad.c @@ -53,6 +53,12 @@ int padding_depad(const unsigned char *data, unsigned long *length, unsigned lon /* nop */ break; #endif + case LTC_PAD_SSH: + pad = 0x1; + for (n = unpadded_length; n < padded_length; ++n) { + if (data[n] != pad++) return CRYPT_INVALID_PACKET; + } + break; case LTC_PAD_ONE_AND_ZERO: while (unpadded_length > 0 && data[unpadded_length - 1] != 0x80) { if (data[unpadded_length - 1] != 0x0) return CRYPT_INVALID_PACKET; diff --git a/src/ltc/misc/padding/padding_pad.c b/src/ltc/misc/padding/padding_pad.c index 8a775b3d..7d8bbbad 100644 --- a/src/ltc/misc/padding/padding_pad.c +++ b/src/ltc/misc/padding/padding_pad.c @@ -32,6 +32,7 @@ static int s_padding_padded_length(unsigned long *length, unsigned long mode) case LTC_PAD_PKCS7: case LTC_PAD_ONE_AND_ZERO: case LTC_PAD_ZERO_ALWAYS: + case LTC_PAD_SSH: t = 1; break; #ifdef LTC_RNG_GET_BYTES @@ -78,10 +79,10 @@ static int s_padding_padded_length(unsigned long *length, unsigned long mode) */ int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded_length, unsigned long mode) { - unsigned long l; + unsigned long l, n; enum padding_type type; int err; - unsigned char diff; + unsigned char diff, pad; LTC_ARGCHK(data != NULL); LTC_ARGCHK(padded_length != NULL); @@ -125,6 +126,12 @@ int padding_pad(unsigned char *data, unsigned long length, unsigned long* padded XMEMSET(&data[length], 0, diff-1); data[l-1] = diff; break; + case LTC_PAD_SSH: + pad = 0x1; + for (n = length; n < l; ++n) { + data[n] = pad++; + } + break; case LTC_PAD_ONE_AND_ZERO: XMEMSET(&data[length + 1], 0, diff); data[length] = 0x80; diff --git a/src/ltc/misc/pkcs12/pkcs12_kdf.c b/src/ltc/misc/pkcs12/pkcs12_kdf.c index 6bbdd168..1739af73 100644 --- a/src/ltc/misc/pkcs12/pkcs12_kdf.c +++ b/src/ltc/misc/pkcs12/pkcs12_kdf.c @@ -39,7 +39,7 @@ int pkcs12_kdf( int hash_id, for (i = 0; i < c; i++) { Alen = sizeof(A); - err = hash_memory_multi(hash_id, A, &Alen, D, v, I, Slen + Plen, NULL); /* A = HASH(D || I) */ + err = hash_memory_multi(hash_id, A, &Alen, D, v, I, Slen + Plen, LTC_NULL); /* A = HASH(D || I) */ if (err != CRYPT_OK) goto DONE; for (j = 1; j < iterations; j++) { err = hash_memory(hash_id, A, Alen, A, &Alen); /* A = HASH(A) */ diff --git a/src/ltc/misc/ssh/ssh_encode_sequence_multi.c b/src/ltc/misc/ssh/ssh_encode_sequence_multi.c index d2be6897..4bec5e12 100644 --- a/src/ltc/misc/ssh/ssh_encode_sequence_multi.c +++ b/src/ltc/misc/ssh/ssh_encode_sequence_multi.c @@ -134,7 +134,7 @@ int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) STORE32H(size, out); out += 4; } - if ((err = mp_to_unsigned_bin(vdata, out)) != CRYPT_OK) { + if (mp_to_unsigned_bin(vdata, out) != CRYPT_OK) { err = CRYPT_ERROR; goto error; } diff --git a/src/ltc/pk/asn1/der/custom_type/der_encode_custom_type.c b/src/ltc/pk/asn1/der/custom_type/der_encode_custom_type.c index 2e21b4aa..586fb316 100644 --- a/src/ltc/pk/asn1/der/custom_type/der_encode_custom_type.c +++ b/src/ltc/pk/asn1/der/custom_type/der_encode_custom_type.c @@ -36,7 +36,7 @@ int der_encode_custom_type(const ltc_asn1_list *root, /* get size of output that will be required */ y = 0; z = 0; - if ((err = der_length_custom_type(root, &y, &z)) != CRYPT_OK) return CRYPT_INVALID_ARG; + if (der_length_custom_type(root, &y, &z) != CRYPT_OK) return CRYPT_INVALID_ARG; /* too big ? */ if (*outlen < y) { @@ -46,7 +46,7 @@ int der_encode_custom_type(const ltc_asn1_list *root, } /* get length of the identifier, so we know the offset where to start writing */ - if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) return CRYPT_INVALID_ARG; + if (der_length_asn1_identifier(root, &id_len) != CRYPT_OK) return CRYPT_INVALID_ARG; x = id_len; diff --git a/src/ltc/pk/asn1/der/sequence/der_decode_sequence_multi.c b/src/ltc/pk/asn1/der/sequence/der_decode_sequence_multi.c index 8807e910..776c2ed7 100644 --- a/src/ltc/pk/asn1/der/sequence/der_decode_sequence_multi.c +++ b/src/ltc/pk/asn1/der/sequence/der_decode_sequence_multi.c @@ -34,15 +34,16 @@ static int s_der_decode_sequence_va(const unsigned char *in, unsigned long inlen x = 0; for (;;) { type = (ltc_asn1_type)va_arg(a1, int); - size = va_arg(a1, unsigned long); - data = va_arg(a1, void*); - LTC_UNUSED_PARAM(size); - LTC_UNUSED_PARAM(data); if (type == LTC_ASN1_EOL) { break; } + size = va_arg(a1, unsigned long); + data = va_arg(a1, void*); + LTC_UNUSED_PARAM(size); + LTC_UNUSED_PARAM(data); + switch (type) { case LTC_ASN1_BOOLEAN: case LTC_ASN1_INTEGER: diff --git a/src/ltc/pk/asn1/der/sequence/der_encode_sequence_ex.c b/src/ltc/pk/asn1/der/sequence/der_encode_sequence_ex.c index d5c81bbd..2ea33a6d 100644 --- a/src/ltc/pk/asn1/der/sequence/der_encode_sequence_ex.c +++ b/src/ltc/pk/asn1/der/sequence/der_encode_sequence_ex.c @@ -33,7 +33,7 @@ int der_encode_sequence_ex(const ltc_asn1_list *list, unsigned long inlen, /* get size of output that will be required */ y = 0; z = 0; - if ((err = der_length_sequence_ex(list, inlen, &y, &z)) != CRYPT_OK) return CRYPT_INVALID_ARG; + if (der_length_sequence_ex(list, inlen, &y, &z) != CRYPT_OK) return CRYPT_INVALID_ARG; /* too big ? */ if (*outlen < y) { diff --git a/src/ltc/pk/asn1/der/sequence/der_encode_sequence_multi.c b/src/ltc/pk/asn1/der/sequence/der_encode_sequence_multi.c index c0dc09b4..615488d7 100644 --- a/src/ltc/pk/asn1/der/sequence/der_encode_sequence_multi.c +++ b/src/ltc/pk/asn1/der/sequence/der_encode_sequence_multi.c @@ -35,15 +35,16 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) x = 0; for (;;) { type = (ltc_asn1_type)va_arg(args, int); - size = va_arg(args, unsigned long); - data = va_arg(args, void*); - LTC_UNUSED_PARAM(size); - LTC_UNUSED_PARAM(data); if (type == LTC_ASN1_EOL) { break; } + size = va_arg(args, unsigned long); + data = va_arg(args, void*); + LTC_UNUSED_PARAM(size); + LTC_UNUSED_PARAM(data); + switch (type) { case LTC_ASN1_BOOLEAN: case LTC_ASN1_INTEGER: @@ -89,13 +90,14 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...) x = 0; for (;;) { type = (ltc_asn1_type)va_arg(args, int); - size = va_arg(args, unsigned long); - data = va_arg(args, void*); if (type == LTC_ASN1_EOL) { break; } + size = va_arg(args, unsigned long); + data = va_arg(args, void*); + switch (type) { case LTC_ASN1_BOOLEAN: case LTC_ASN1_INTEGER: diff --git a/src/ltc/pk/asn1/der/short_integer/der_decode_short_integer.c b/src/ltc/pk/asn1/der/short_integer/der_decode_short_integer.c index e596e072..e00702d1 100644 --- a/src/ltc/pk/asn1/der/short_integer/der_decode_short_integer.c +++ b/src/ltc/pk/asn1/der/short_integer/der_decode_short_integer.c @@ -42,6 +42,10 @@ int der_decode_short_integer(const unsigned char *in, unsigned long inlen, unsig return CRYPT_INVALID_PACKET; } + if (len > sizeof(unsigned long)) { + return CRYPT_OVERFLOW; + } + /* read number */ y = 0; while (len--) { diff --git a/src/ltc/pk/asn1/oid/pk_get_oid.c b/src/ltc/pk/asn1/oid/pk_get_oid.c index 618cc801..b3e1ee26 100644 --- a/src/ltc/pk/asn1/oid/pk_get_oid.c +++ b/src/ltc/pk/asn1/oid/pk_get_oid.c @@ -10,12 +10,12 @@ typedef struct { } oid_table_entry; static const oid_table_entry pka_oids[] = { - { PKA_RSA, "1.2.840.113549.1.1.1" }, - { PKA_DSA, "1.2.840.10040.4.1" }, - { PKA_EC, "1.2.840.10045.2.1" }, - { PKA_EC_PRIMEF, "1.2.840.10045.1.1" }, - { PKA_X25519, "1.3.101.110" }, - { PKA_ED25519, "1.3.101.112" }, + { LTC_OID_RSA, "1.2.840.113549.1.1.1" }, + { LTC_OID_DSA, "1.2.840.10040.4.1" }, + { LTC_OID_EC, "1.2.840.10045.2.1" }, + { LTC_OID_EC_PRIMEF, "1.2.840.10045.1.1" }, + { LTC_OID_X25519, "1.3.101.110" }, + { LTC_OID_ED25519, "1.3.101.112" }, }; /* diff --git a/src/ltc/pk/asn1/oid/pk_oid_str.c b/src/ltc/pk/asn1/oid/pk_oid_str.c index aa889631..bc21a6f5 100644 --- a/src/ltc/pk/asn1/oid/pk_oid_str.c +++ b/src/ltc/pk/asn1/oid/pk_oid_str.c @@ -49,7 +49,7 @@ int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, char tmp[256] = { 0 }; LTC_ARGCHK(oid != NULL); - LTC_ARGCHK(OID != NULL); + LTC_ARGCHK(oidlen < INT_MAX); LTC_ARGCHK(outlen != NULL); for (i = oidlen - 1, k = 0; i >= 0; i--) { @@ -74,6 +74,7 @@ int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, *outlen = k + 1; return CRYPT_BUFFER_OVERFLOW; } + LTC_ARGCHK(OID != NULL); for (j = 0; j < k; j++) OID[j] = tmp[k - j - 1]; OID[k] = '\0'; *outlen = k; /* the length without terminating NUL byte */ diff --git a/src/ltc/pk/asn1/x509/x509_decode_public_key_from_certificate.c b/src/ltc/pk/asn1/x509/x509_decode_public_key_from_certificate.c index 23822262..feff868f 100644 --- a/src/ltc/pk/asn1/x509/x509_decode_public_key_from_certificate.c +++ b/src/ltc/pk/asn1/x509/x509_decode_public_key_from_certificate.c @@ -81,7 +81,7 @@ int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned lo if ((l->type == LTC_ASN1_SEQUENCE) && (l->data != NULL) && LOOKS_LIKE_SPKI(l->child)) { - if (algorithm == PKA_EC) { + if (algorithm == LTC_OID_EC) { err = callback(l->data, l->size, ctx); } else { err = x509_decode_subject_public_key_info(l->data, l->size, diff --git a/src/ltc/pk/dh/dh_free.c b/src/ltc/pk/dh/dh_free.c index b149a94e..ff56b006 100644 --- a/src/ltc/pk/dh/dh_free.c +++ b/src/ltc/pk/dh/dh_free.c @@ -12,7 +12,7 @@ void dh_free(dh_key *key) { LTC_ARGCHKVD(key != NULL); - mp_cleanup_multi(&key->prime, &key->base, &key->y, &key->x, NULL); + mp_cleanup_multi(&key->prime, &key->base, &key->y, &key->x, LTC_NULL); } #endif /* LTC_MDH */ diff --git a/src/ltc/pk/dh/dh_import.c b/src/ltc/pk/dh/dh_import.c index 5db1be38..a067a327 100644 --- a/src/ltc/pk/dh/dh_import.c +++ b/src/ltc/pk/dh/dh_import.c @@ -22,7 +22,7 @@ int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key) LTC_ARGCHK(key != NULL); /* init */ - if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { return err; } diff --git a/src/ltc/pk/dh/dh_set.c b/src/ltc/pk/dh/dh_set.c index 1f094f20..e25db089 100644 --- a/src/ltc/pk/dh/dh_set.c +++ b/src/ltc/pk/dh/dh_set.c @@ -26,7 +26,7 @@ int dh_set_pg(const unsigned char *p, unsigned long plen, LTC_ARGCHK(g != NULL); LTC_ARGCHK(ltc_mp.name != NULL); - if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { return err; } @@ -58,7 +58,7 @@ int dh_set_pg_groupsize(int groupsize, dh_key *key) for (i = 0; (groupsize > ltc_dh_sets[i].size) && (ltc_dh_sets[i].size != 0); i++); if (ltc_dh_sets[i].size == 0) return CRYPT_INVALID_KEYSIZE; - if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { return err; } if ((err = mp_read_radix(key->base, ltc_dh_sets[i].base, 16)) != CRYPT_OK) { goto LBL_ERR; } diff --git a/src/ltc/pk/dh/dh_set_pg_dhparam.c b/src/ltc/pk/dh/dh_set_pg_dhparam.c index 972c6ac0..1f2fb3b9 100644 --- a/src/ltc/pk/dh/dh_set_pg_dhparam.c +++ b/src/ltc/pk/dh/dh_set_pg_dhparam.c @@ -24,7 +24,7 @@ int dh_set_pg_dhparam(const unsigned char *dhparam, unsigned long dhparamlen, dh LTC_ARGCHK(dhparam != NULL); LTC_ARGCHK(dhparamlen > 0); - if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, LTC_NULL)) != CRYPT_OK) { return err; } if ((err = der_decode_sequence_multi(dhparam, dhparamlen, diff --git a/src/ltc/pk/dsa/dsa_encrypt_key.c b/src/ltc/pk/dsa/dsa_encrypt_key.c index c2b7e9d7..2f460921 100644 --- a/src/ltc/pk/dsa/dsa_encrypt_key.c +++ b/src/ltc/pk/dsa/dsa_encrypt_key.c @@ -50,7 +50,7 @@ int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, } /* make a random key and export the public copy */ - if ((err = mp_init_multi(&g_pub, &g_priv, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&g_pub, &g_priv, LTC_NULL)) != CRYPT_OK) { return err; } @@ -63,7 +63,7 @@ int dsa_encrypt_key(const unsigned char *in, unsigned long inlen, if (skey != NULL) { XFREE(skey); } - mp_clear_multi(g_pub, g_priv, NULL); + mp_clear_multi(g_pub, g_priv, LTC_NULL); return CRYPT_MEM; } @@ -111,7 +111,7 @@ LBL_ERR: XFREE(skey); XFREE(expt); - mp_clear_multi(g_pub, g_priv, NULL); + mp_clear_multi(g_pub, g_priv, LTC_NULL); return err; } diff --git a/src/ltc/pk/dsa/dsa_export.c b/src/ltc/pk/dsa/dsa_export.c index 8f22ab8a..3550cbec 100644 --- a/src/ltc/pk/dsa/dsa_export.c +++ b/src/ltc/pk/dsa/dsa_export.c @@ -75,7 +75,7 @@ int dsa_export(unsigned char *out, unsigned long *outlen, int type, const dsa_ke LTC_SET_ASN1(int_list, 1, LTC_ASN1_INTEGER, key->q, 1UL); LTC_SET_ASN1(int_list, 2, LTC_ASN1_INTEGER, key->g, 1UL); - err = x509_encode_subject_public_key_info(out, outlen, PKA_DSA, tmp, + err = x509_encode_subject_public_key_info(out, outlen, LTC_OID_DSA, tmp, tmplen, LTC_ASN1_SEQUENCE, int_list, sizeof(int_list) / sizeof(int_list[0])); diff --git a/src/ltc/pk/dsa/dsa_free.c b/src/ltc/pk/dsa/dsa_free.c index dc54f57f..dbe86253 100644 --- a/src/ltc/pk/dsa/dsa_free.c +++ b/src/ltc/pk/dsa/dsa_free.c @@ -16,7 +16,7 @@ void dsa_free(dsa_key *key) { LTC_ARGCHKVD(key != NULL); - mp_cleanup_multi(&key->y, &key->x, &key->q, &key->g, &key->p, NULL); + mp_cleanup_multi(&key->y, &key->x, &key->q, &key->g, &key->p, LTC_NULL); key->type = key->qord = 0; } diff --git a/src/ltc/pk/dsa/dsa_generate_pqg.c b/src/ltc/pk/dsa/dsa_generate_pqg.c index a2d54382..22f4852b 100644 --- a/src/ltc/pk/dsa/dsa_generate_pqg.c +++ b/src/ltc/pk/dsa/dsa_generate_pqg.c @@ -108,7 +108,7 @@ static int s_dsa_make_params(prng_state *prng, int wprng, int group_size, int mo if ((wbuf = XMALLOC((n+1)*outbytes)) == NULL) { err = CRYPT_MEM; goto cleanup3; } if ((sbuf = XMALLOC(seedbytes)) == NULL) { err = CRYPT_MEM; goto cleanup2; } - err = mp_init_multi(&t2L1, &t2N1, &t2q, &t2seedlen, &U, &W, &X, &c, &h, &e, &seedinc, NULL); + err = mp_init_multi(&t2L1, &t2N1, &t2q, &t2seedlen, &U, &W, &X, &c, &h, &e, &seedinc, LTC_NULL); if (err != CRYPT_OK) { goto cleanup1; } if ((err = mp_2expt(t2L1, L-1)) != CRYPT_OK) { goto cleanup; } @@ -187,7 +187,7 @@ static int s_dsa_make_params(prng_state *prng, int wprng, int group_size, int mo err = CRYPT_OK; cleanup: - mp_clear_multi(t2L1, t2N1, t2q, t2seedlen, U, W, X, c, h, e, seedinc, NULL); + mp_clear_multi(t2L1, t2N1, t2q, t2seedlen, U, W, X, c, h, e, seedinc, LTC_NULL); cleanup1: XFREE(sbuf); cleanup2: @@ -213,7 +213,7 @@ int dsa_generate_pqg(prng_state *prng, int wprng, int group_size, int modulus_si LTC_ARGCHK(ltc_mp.name != NULL); /* init mp_ints */ - if ((err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL)) != CRYPT_OK) { return err; } /* generate params */ diff --git a/src/ltc/pk/dsa/dsa_import.c b/src/ltc/pk/dsa/dsa_import.c index a1d22818..b5660d39 100644 --- a/src/ltc/pk/dsa/dsa_import.c +++ b/src/ltc/pk/dsa/dsa_import.c @@ -28,7 +28,7 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) LTC_ARGCHK(ltc_mp.name != NULL); /* init key */ - if (mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL) != CRYPT_OK) { + if (mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL) != CRYPT_OK) { return CRYPT_MEM; } @@ -72,14 +72,14 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) } } /* get key type */ - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_SHORT_INTEGER, 1UL, &zero, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->g, - LTC_ASN1_INTEGER, 1UL, key->y, - LTC_ASN1_INTEGER, 1UL, key->x, - LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) { + if (der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &zero, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->g, + LTC_ASN1_INTEGER, 1UL, key->y, + LTC_ASN1_INTEGER, 1UL, key->x, + LTC_ASN1_EOL, 0UL, NULL) == CRYPT_OK) { key->type = PK_PRIVATE; } else { /* public */ @@ -97,7 +97,7 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) } len = 3; - err = x509_decode_subject_public_key_info(in, inlen, PKA_DSA, + err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_DSA, tmpbuf, &tmpbuf_len, LTC_ASN1_SEQUENCE, params, &len); if (err != CRYPT_OK) { diff --git a/src/ltc/pk/dsa/dsa_set.c b/src/ltc/pk/dsa/dsa_set.c index 026f2806..82b60333 100644 --- a/src/ltc/pk/dsa/dsa_set.c +++ b/src/ltc/pk/dsa/dsa_set.c @@ -30,7 +30,7 @@ int dsa_set_pqg(const unsigned char *p, unsigned long plen, LTC_ARGCHK(ltc_mp.name != NULL); /* init key */ - err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL); + err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL); if (err != CRYPT_OK) return err; if ((err = mp_read_unsigned_bin(key->p, (unsigned char *)p , plen)) != CRYPT_OK) { goto LBL_ERR; } diff --git a/src/ltc/pk/dsa/dsa_set_pqg_dsaparam.c b/src/ltc/pk/dsa/dsa_set_pqg_dsaparam.c index 3ab92282..97c71f10 100644 --- a/src/ltc/pk/dsa/dsa_set_pqg_dsaparam.c +++ b/src/ltc/pk/dsa/dsa_set_pqg_dsaparam.c @@ -25,7 +25,7 @@ int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamle LTC_ARGCHK(ltc_mp.name != NULL); /* init key */ - err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL); + err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, LTC_NULL); if (err != CRYPT_OK) return err; if ((err = der_decode_sequence_multi(dsaparam, dsaparamlen, diff --git a/src/ltc/pk/dsa/dsa_sign_hash.c b/src/ltc/pk/dsa/dsa_sign_hash.c index c4ba0bc1..56baa803 100644 --- a/src/ltc/pk/dsa/dsa_sign_hash.c +++ b/src/ltc/pk/dsa/dsa_sign_hash.c @@ -51,7 +51,7 @@ int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen, } /* Init our temps */ - if ((err = mp_init_multi(&k, &kinv, &tmp, NULL)) != CRYPT_OK) { goto ERRBUF; } + if ((err = mp_init_multi(&k, &kinv, &tmp, LTC_NULL)) != CRYPT_OK) { goto ERRBUF; } qbits = mp_count_bits(key->q); retry: @@ -89,7 +89,7 @@ retry: err = CRYPT_OK; error: - mp_clear_multi(k, kinv, tmp, NULL); + mp_clear_multi(k, kinv, tmp, LTC_NULL); ERRBUF: #ifdef LTC_CLEAN_STACK zeromem(buf, LTC_MDSA_MAX_GROUP); @@ -121,7 +121,7 @@ int dsa_sign_hash(const unsigned char *in, unsigned long inlen, LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); - if (mp_init_multi(&r, &s, NULL) != CRYPT_OK) { + if (mp_init_multi(&r, &s, LTC_NULL) != CRYPT_OK) { return CRYPT_MEM; } @@ -135,7 +135,7 @@ int dsa_sign_hash(const unsigned char *in, unsigned long inlen, LTC_ASN1_EOL, 0UL, NULL); error: - mp_clear_multi(r, s, NULL); + mp_clear_multi(r, s, LTC_NULL); return err; } diff --git a/src/ltc/pk/dsa/dsa_verify_hash.c b/src/ltc/pk/dsa/dsa_verify_hash.c index e290ba16..500feda9 100644 --- a/src/ltc/pk/dsa/dsa_verify_hash.c +++ b/src/ltc/pk/dsa/dsa_verify_hash.c @@ -36,7 +36,7 @@ int dsa_verify_hash_raw( void *r, void *s, *stat = 0; /* init our variables */ - if ((err = mp_init_multi(&w, &v, &u1, &u2, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&w, &v, &u1, &u2, LTC_NULL)) != CRYPT_OK) { return err; } @@ -72,7 +72,7 @@ int dsa_verify_hash_raw( void *r, void *s, err = CRYPT_OK; error: - mp_clear_multi(w, v, u1, u2, NULL); + mp_clear_multi(w, v, u1, u2, LTC_NULL); return err; } @@ -98,7 +98,7 @@ int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, LTC_ARGCHK(stat != NULL); *stat = 0; /* must be set before the first return */ - if ((err = mp_init_multi(&r, &s, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) { return err; } @@ -119,7 +119,7 @@ int dsa_verify_hash(const unsigned char *sig, unsigned long siglen, err = dsa_verify_hash_raw(r, s, hash, hashlen, stat, key); LBL_ERR: - mp_clear_multi(r, s, NULL); + mp_clear_multi(r, s, LTC_NULL); return err; } diff --git a/src/ltc/pk/dsa/dsa_verify_key.c b/src/ltc/pk/dsa/dsa_verify_key.c index 4f4bdd17..50d566ae 100644 --- a/src/ltc/pk/dsa/dsa_verify_key.c +++ b/src/ltc/pk/dsa/dsa_verify_key.c @@ -62,7 +62,7 @@ int dsa_int_validate_pqg(const dsa_key *key, int *stat) return CRYPT_OK; } - if ((err = mp_init_multi(&tmp1, &tmp2, NULL)) != CRYPT_OK) { return err; } + if ((err = mp_init_multi(&tmp1, &tmp2, LTC_NULL)) != CRYPT_OK) { return err; } /* FIPS 186-4 chapter 4.1: q is a divisor of (p - 1) */ if ((err = mp_sub_d(key->p, 1, tmp1)) != CRYPT_OK) { goto error; } @@ -84,7 +84,7 @@ int dsa_int_validate_pqg(const dsa_key *key, int *stat) err = CRYPT_OK; *stat = 1; error: - mp_clear_multi(tmp2, tmp1, NULL); + mp_clear_multi(tmp2, tmp1, LTC_NULL); return err; } diff --git a/src/ltc/pk/ec25519/ec25519_crypto_ctx.c b/src/ltc/pk/ec25519/ec25519_crypto_ctx.c new file mode 100644 index 00000000..e1efb301 --- /dev/null +++ b/src/ltc/pk/ec25519/ec25519_crypto_ctx.c @@ -0,0 +1,41 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file ec25519_crypto_ctx.c + curve25519 crypto context helper +*/ + +#ifdef LTC_CURVE25519 + +int ec25519_crypto_ctx(unsigned char *out, unsigned long *outlen, unsigned char flag, const unsigned char *ctx, unsigned long ctxlen) +{ + unsigned char *buf = out; + + const char *prefix = "SigEd25519 no Ed25519 collisions"; + const unsigned long prefix_len = XSTRLEN(prefix); + const unsigned char ctxlen8 = (unsigned char)ctxlen; + + if (ctxlen > 255u) return CRYPT_INPUT_TOO_LONG; + if (*outlen < prefix_len + 2u + ctxlen) return CRYPT_BUFFER_OVERFLOW; + + XMEMCPY(buf, prefix, prefix_len); + buf += prefix_len; + XMEMCPY(buf, &flag, 1); + buf++; + XMEMCPY(buf, &ctxlen8, 1); + buf++; + + if (ctxlen > 0u) { + LTC_ARGCHK(ctx != NULL); + XMEMCPY(buf, ctx, ctxlen); + buf += ctxlen; + } + + *outlen = buf-out; + + return CRYPT_OK; +} + +#endif diff --git a/src/ltc/pk/ec25519/tweetnacl.c b/src/ltc/pk/ec25519/tweetnacl.c index fc5aad72..9db0dcd8 100644 --- a/src/ltc/pk/ec25519/tweetnacl.c +++ b/src/ltc/pk/ec25519/tweetnacl.c @@ -221,18 +221,22 @@ int tweetnacl_crypto_scalarmult_base(u8 *q,const u8 *n) return tweetnacl_crypto_scalarmult(q,n,nine); } -static int tweetnacl_crypto_hash(u8 *out,const u8 *m,u64 n) +static LTC_INLINE int tweetnacl_crypto_hash_ctx(u8 *out,const u8 *m,u64 n,const u8 *ctx,u32 cs) { - unsigned long len; - int err, hash_idx; + unsigned long len = 64; + int hash_idx = find_hash("sha512"); if (n > ULONG_MAX) return CRYPT_OVERFLOW; - hash_idx = find_hash("sha512"); - len = 64; - if ((err = hash_memory(hash_idx, m, n, out, &len)) != CRYPT_OK) return err; + if(cs == 0) + return hash_memory(hash_idx, m, n, out, &len); - return 0; + return hash_memory_multi(hash_idx, out, &len, ctx, cs, m, n, LTC_NULL); +} + +static LTC_INLINE int tweetnacl_crypto_hash(u8 *out,const u8 *m,u64 n) +{ + return tweetnacl_crypto_hash_ctx(out, m, n, NULL, 0); } sv add(gf p[4],gf q[4]) @@ -376,7 +380,7 @@ sv reduce(u8 *r) modL(r,x); } -int tweetnacl_crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 mlen,const u8 *sk,const u8 *pk) +int tweetnacl_crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 mlen,const u8 *sk,const u8 *pk, const u8 *ctx, u64 cs) { u8 d[64],h[64],r[64]; i64 i,j,x[64]; @@ -391,13 +395,13 @@ int tweetnacl_crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 mlen,const u8 *sk,co FOR(i,(i64)mlen) sm[64 + i] = m[i]; FOR(i,32) sm[32 + i] = d[32 + i]; - tweetnacl_crypto_hash(r, sm+32, mlen+32); + tweetnacl_crypto_hash_ctx(r, sm+32, mlen+32,ctx,cs); reduce(r); scalarbase(p,r); pack(sm,p); FOR(i,32) sm[i+32] = pk[i]; - tweetnacl_crypto_hash(h,sm,mlen + 64); + tweetnacl_crypto_hash_ctx(h,sm,mlen + 64,ctx,cs); reduce(h); FOR(i,64) x[i] = 0; @@ -444,7 +448,7 @@ static int unpackneg(gf r[4],const u8 p[32]) return 0; } -int tweetnacl_crypto_sign_open(int *stat, u8 *m,u64 *mlen,const u8 *sm,u64 smlen,const u8 *pk) +int tweetnacl_crypto_sign_open(int *stat, u8 *m,u64 *mlen,const u8 *sm,u64 smlen,const u8 *ctx,u64 cs,const u8 *pk) { u64 i; u8 s[32],t[32],h[64]; @@ -460,7 +464,7 @@ int tweetnacl_crypto_sign_open(int *stat, u8 *m,u64 *mlen,const u8 *sm,u64 smlen XMEMMOVE(m,sm,smlen); XMEMMOVE(s,m + 32,32); XMEMMOVE(m + 32,pk,32); - tweetnacl_crypto_hash(h,m,smlen); + tweetnacl_crypto_hash_ctx(h,m,smlen,ctx,cs); reduce(h); scalarmult(p,q,h); @@ -480,3 +484,8 @@ int tweetnacl_crypto_sign_open(int *stat, u8 *m,u64 *mlen,const u8 *sm,u64 smlen *mlen = smlen; return CRYPT_OK; } + +int tweetnacl_crypto_ph(u8 *out,const u8 *msg,u64 msglen) +{ + return tweetnacl_crypto_hash(out, msg, msglen); +} diff --git a/src/ltc/pk/ecc/ecc_export_openssl.c b/src/ltc/pk/ecc/ecc_export_openssl.c index 97123d64..2e899968 100644 --- a/src/ltc/pk/ecc/ecc_export_openssl.c +++ b/src/ltc/pk/ecc/ecc_export_openssl.c @@ -34,41 +34,6 @@ int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, cons if (key->type != PK_PRIVATE && flag_pri) return CRYPT_PK_TYPE_MISMATCH; - prime = key->dp.prime; - order = key->dp.order; - b = key->dp.B; - a = key->dp.A; - gx = key->dp.base.x; - gy = key->dp.base.y; - - /* curve param a */ - len_a = mp_unsigned_bin_size(a); - if (len_a > sizeof(bin_a)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } - if ((err = mp_to_unsigned_bin(a, bin_a)) != CRYPT_OK) { goto error; } - if (len_a == 0) { len_a = 1; bin_a[0] = 0; } /* handle case a == 0 */ - - /* curve param b */ - len_b = mp_unsigned_bin_size(b); - if (len_b > sizeof(bin_b)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } - if ((err = mp_to_unsigned_bin(b, bin_b)) != CRYPT_OK) { goto error; } - if (len_b == 0) { len_b = 1; bin_b[0] = 0; } /* handle case b == 0 */ - - /* base point - (un)compressed based on flag_com */ - len_g = sizeof(bin_g); - err = ltc_ecc_export_point(bin_g, &len_g, gx, gy, key->dp.size, flag_com); - if (err != CRYPT_OK) { goto error; } - - /* public key - (un)compressed based on flag_com */ - len_xy = sizeof(bin_xy); - err = ltc_ecc_export_point(bin_xy, &len_xy, key->pubkey.x, key->pubkey.y, key->dp.size, flag_com); - if (err != CRYPT_OK) { goto error; } - - /* co-factor */ - cofactor = key->dp.cofactor; - - /* we support only prime-field EC */ - if ((err = pk_get_oid(PKA_EC_PRIMEF, &OID)) != CRYPT_OK) { goto error; } - if (flag_oid) { /* http://tools.ietf.org/html/rfc5912 ECParameters ::= CHOICE { @@ -79,6 +44,34 @@ int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, cons LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_OBJECT_IDENTIFIER, key->dp.oid, key->dp.oidlen); } else { + prime = key->dp.prime; + order = key->dp.order; + a = key->dp.A; + b = key->dp.B; + gx = key->dp.base.x; + gy = key->dp.base.y; + cofactor = key->dp.cofactor; + + /* curve param a */ + len_a = mp_unsigned_bin_size(a); + if (len_a > sizeof(bin_a)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } + if ((err = mp_to_unsigned_bin(a, bin_a)) != CRYPT_OK) { goto error; } + if (len_a == 0) { len_a = 1; bin_a[0] = 0; } /* handle case a == 0 */ + + /* curve param b */ + len_b = mp_unsigned_bin_size(b); + if (len_b > sizeof(bin_b)) { err = CRYPT_BUFFER_OVERFLOW; goto error; } + if ((err = mp_to_unsigned_bin(b, bin_b)) != CRYPT_OK) { goto error; } + if (len_b == 0) { len_b = 1; bin_b[0] = 0; } /* handle case b == 0 */ + + /* base point - (un)compressed based on flag_com */ + len_g = sizeof(bin_g); + err = ltc_ecc_export_point(bin_g, &len_g, gx, gy, key->dp.size, flag_com); + if (err != CRYPT_OK) { goto error; } + + /* we support only prime-field EC */ + if ((err = pk_get_oid(LTC_OID_EC_PRIMEF, &OID)) != CRYPT_OK) { goto error; } + /* http://tools.ietf.org/html/rfc3279 ECParameters ::= SEQUENCE { # SEQUENCE version INTEGER { ecpVer1(1) } (ecpVer1) # INTEGER :01 @@ -122,7 +115,15 @@ int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, cons LTC_SET_ASN1(&ecparams, 0, LTC_ASN1_SEQUENCE, seq_ecparams, 6UL); } + /* public key - (un)compressed based on flag_com */ + len_xy = sizeof(bin_xy); + err = ltc_ecc_export_point(bin_xy, &len_xy, key->pubkey.x, key->pubkey.y, key->dp.size, flag_com); + if (err != CRYPT_OK) { + goto error; + } + if (flag_pri) { + /* http://tools.ietf.org/html/rfc5915 ECPrivateKey ::= SEQUENCE { # SEQUENCE version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1) # INTEGER :01 @@ -155,7 +156,7 @@ int ecc_export_openssl(unsigned char *out, unsigned long *outlen, int type, cons subjectPublicKey BIT STRING # BIT STRING } */ - err = x509_encode_subject_public_key_info( out, outlen, PKA_EC, bin_xy, len_xy, + err = x509_encode_subject_public_key_info( out, outlen, LTC_OID_EC, bin_xy, len_xy, ecparams.type, ecparams.data, ecparams.size ); } diff --git a/src/ltc/pk/ecc/ecc_import_openssl.c b/src/ltc/pk/ecc/ecc_import_openssl.c index e3a6f619..325b0b05 100644 --- a/src/ltc/pk/ecc/ecc_import_openssl.c +++ b/src/ltc/pk/ecc/ecc_import_openssl.c @@ -49,7 +49,7 @@ static int s_ecc_import_private_with_curve(const unsigned char *in, unsigned lon unsigned long cofactor = 0, ecver = 0, pkver = 0, tmpoid[16]; int err; - if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, LTC_NULL)) != CRYPT_OK) { return err; } @@ -95,7 +95,7 @@ static int s_ecc_import_private_with_curve(const unsigned char *in, unsigned lon err = ecc_set_key(bin_k, len_k, PK_PRIVATE, key); } error: - mp_clear_multi(prime, order, a, b, gx, gy, NULL); + mp_clear_multi(prime, order, a, b, gx, gy, LTC_NULL); return err; } diff --git a/src/ltc/pk/ecc/ecc_import_pkcs8.c b/src/ltc/pk/ecc/ecc_import_pkcs8.c index 0461db09..81ac6ed6 100644 --- a/src/ltc/pk/ecc/ecc_import_pkcs8.c +++ b/src/ltc/pk/ecc/ecc_import_pkcs8.c @@ -56,15 +56,15 @@ int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, LTC_ARGCHK(ltc_mp.name != NULL); /* get EC alg oid */ - err = pk_get_oid(PKA_EC, &pka_ec_oid); + err = pk_get_oid(LTC_OID_EC, &pka_ec_oid); if (err != CRYPT_OK) return err; /* init key */ - err = mp_init_multi(&a, &b, &gx, &gy, NULL); + err = mp_init_multi(&a, &b, &gx, &gy, LTC_NULL); if (err != CRYPT_OK) return err; - if ((err = pkcs8_decode_flexi(in, inlen, pwd, pwdlen, &l)) == CRYPT_OK) { + if (pkcs8_decode_flexi(in, inlen, pwd, pwdlen, &l) == CRYPT_OK) { /* Setup for basic structure */ n=0; @@ -73,7 +73,7 @@ int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, &priv_key); LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); - if (((err = s_der_flexi_sequence_cmp(l, flexi_should)) == CRYPT_OK) && + if ((s_der_flexi_sequence_cmp(l, flexi_should) == CRYPT_OK) && (pk_oid_cmp_with_asn1(pka_ec_oid, seq->child) == CRYPT_OK)) { ltc_asn1_list *version, *field, *point, *point_g, *order, *p_cofactor; @@ -154,7 +154,7 @@ int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, /* load private key value 'k' */ len = priv_key->size; - if ((err = der_decode_sequence_flexi(priv_key->data, &len, &p)) == CRYPT_OK) { + if (der_decode_sequence_flexi(priv_key->data, &len, &p) == CRYPT_OK) { if (p->type == LTC_ASN1_SEQUENCE && LTC_ASN1_IS_TYPE(p->child, LTC_ASN1_INTEGER) && LTC_ASN1_IS_TYPE(p->child->next, LTC_ASN1_OCTET_STRING)) { @@ -177,7 +177,7 @@ int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen, LBL_ECCFREE: ecc_free(key); LBL_DONE: - mp_clear_multi(a, b, gx, gy, NULL); + mp_clear_multi(a, b, gx, gy, LTC_NULL); if (l) der_free_sequence_flexi(l); if (p) der_free_sequence_flexi(p); return err; diff --git a/src/ltc/pk/ecc/ecc_import_x509.c b/src/ltc/pk/ecc/ecc_import_x509.c index 7d64c63f..e4ba5e3a 100644 --- a/src/ltc/pk/ecc/ecc_import_x509.c +++ b/src/ltc/pk/ecc/ecc_import_x509.c @@ -15,7 +15,7 @@ static int s_ecc_import_x509_with_oid(const unsigned char *in, unsigned long inl len_xy = sizeof(bin_xy); len_oid = 16; - err = x509_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy, + err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy, LTC_ASN1_OBJECT_IDENTIFIER, (void *)curveoid, &len_oid); if (err == CRYPT_OK) { /* load curve parameters for given curve OID */ @@ -40,7 +40,7 @@ static int s_ecc_import_x509_with_curve(const unsigned char *in, unsigned long i unsigned long cofactor = 0, ecver = 0, tmpoid[16]; int err; - if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, LTC_NULL)) != CRYPT_OK) { return err; } @@ -63,7 +63,7 @@ static int s_ecc_import_x509_with_curve(const unsigned char *in, unsigned long i /* try to load public key */ len_xy = sizeof(bin_xy); len = 6; - err = x509_decode_subject_public_key_info(in, inlen, PKA_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len); + err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_EC, bin_xy, &len_xy, LTC_ASN1_SEQUENCE, seq_ecparams, &len); if (err == CRYPT_OK) { len_a = seq_curve[0].size; @@ -79,7 +79,7 @@ static int s_ecc_import_x509_with_curve(const unsigned char *in, unsigned long i err = ecc_set_key(bin_xy, len_xy, PK_PUBLIC, key); } error: - mp_clear_multi(prime, order, a, b, gx, gy, NULL); + mp_clear_multi(prime, order, a, b, gx, gy, LTC_NULL); return err; } @@ -107,7 +107,7 @@ success: int ecc_import_x509(const unsigned char *in, unsigned long inlen, ecc_key *key) { return x509_decode_public_key_from_certificate(in, inlen, - PKA_EC, + LTC_OID_EC, LTC_ASN1_EOL, NULL, NULL, (public_key_decode_cb)ecc_import_subject_public_key_info, key); } diff --git a/src/ltc/pk/ecc/ecc_recover_key.c b/src/ltc/pk/ecc/ecc_recover_key.c index ae932767..b6ae644b 100644 --- a/src/ltc/pk/ecc/ecc_recover_key.c +++ b/src/ltc/pk/ecc/ecc_recover_key.c @@ -46,7 +46,7 @@ int ecc_recover_key(const unsigned char *sig, unsigned long siglen, } /* allocate ints */ - if ((err = mp_init_multi(&r, &s, &v, &w, &t1, &t2, &u1, &u2, &v1, &v2, &e, &x, &y, &a_plus3, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&r, &s, &v, &w, &t1, &t2, &u1, &u2, &v1, &v2, &e, &x, &y, &a_plus3, LTC_NULL)) != CRYPT_OK) { return err; } @@ -72,7 +72,7 @@ int ecc_recover_key(const unsigned char *sig, unsigned long siglen, if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, LTC_ASN1_INTEGER, 1UL, r, LTC_ASN1_INTEGER, 1UL, s, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto error; } + LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; } } else if (sigformat == LTC_ECCSIG_RFC7518) { /* RFC7518 format - raw (r,s) */ @@ -120,7 +120,7 @@ int ecc_recover_key(const unsigned char *sig, unsigned long siglen, /* Check curve matches identifier string */ - if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; } + if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; } if ((namelen != name2len) || (XSTRCMP(name, name2) != 0)) { err = CRYPT_INVALID_ARG; goto error; @@ -214,7 +214,7 @@ int ecc_recover_key(const unsigned char *sig, unsigned long siglen, /* for curves with a == -3 keep ma == NULL */ if (mp_cmp(a_plus3, m) != LTC_MP_EQ) { - if ((err = mp_init_multi(&mu, &ma, NULL)) != CRYPT_OK) { goto error; } + if ((err = mp_init_multi(&mu, &ma, LTC_NULL)) != CRYPT_OK) { goto error; } if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; } if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; } } @@ -252,7 +252,7 @@ error: if (mR != NULL) ltc_ecc_del_point(mR); if (mQ != NULL) ltc_ecc_del_point(mQ); if (mG != NULL) ltc_ecc_del_point(mG); - mp_clear_multi(a_plus3, y, x, e, v2, v1, u2, u1, t2, t1, w, v, s, r, NULL); + mp_clear_multi(a_plus3, y, x, e, v2, v1, u2, u1, t2, t1, w, v, s, r, LTC_NULL); return err; } diff --git a/src/ltc/pk/ecc/ecc_sign_hash.c b/src/ltc/pk/ecc/ecc_sign_hash.c index 69c72bd9..229ced19 100644 --- a/src/ltc/pk/ecc/ecc_sign_hash.c +++ b/src/ltc/pk/ecc/ecc_sign_hash.c @@ -46,7 +46,7 @@ int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen, } /* init the bignums */ - if ((err = mp_init_multi(&r, &s, &e, &b, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&r, &s, &e, &b, LTC_NULL)) != CRYPT_OK) { return err; } @@ -174,7 +174,7 @@ int ecc_sign_hash_ex(const unsigned char *in, unsigned long inlen, error: ecc_free(&pubkey); errnokey: - mp_clear_multi(r, s, e, b, NULL); + mp_clear_multi(r, s, e, b, LTC_NULL); return err; } diff --git a/src/ltc/pk/ecc/ecc_ssh_ecdsa_encode_name.c b/src/ltc/pk/ecc/ecc_ssh_ecdsa_encode_name.c index 09c8d643..4b8d5542 100644 --- a/src/ltc/pk/ecc/ecc_ssh_ecdsa_encode_name.c +++ b/src/ltc/pk/ecc/ecc_ssh_ecdsa_encode_name.c @@ -19,7 +19,7 @@ */ int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key) { - char oidstr[64]; + char oidstr[64] = {0}; unsigned long oidlen = sizeof(oidstr); int err, size = 0; diff --git a/src/ltc/pk/ecc/ecc_verify_hash.c b/src/ltc/pk/ecc/ecc_verify_hash.c index 377b4d31..4480ff45 100644 --- a/src/ltc/pk/ecc/ecc_verify_hash.c +++ b/src/ltc/pk/ecc/ecc_verify_hash.c @@ -42,7 +42,7 @@ int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen, *stat = 0; /* allocate ints */ - if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &e, &a_plus3, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &e, &a_plus3, LTC_NULL)) != CRYPT_OK) { return err; } @@ -66,7 +66,7 @@ int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen, if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, LTC_ASN1_INTEGER, 1UL, r, LTC_ASN1_INTEGER, 1UL, s, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto error; } + LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; } } else if (sigformat == LTC_ECCSIG_RFC7518) { /* RFC7518 format - raw (r,s) */ @@ -106,7 +106,7 @@ int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen, /* Check curve matches identifier string */ - if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; } + if ((err = ecc_ssh_ecdsa_encode_name(name2, &name2len, key)) != CRYPT_OK) { goto error; } if ((namelen != name2len) || (XSTRCMP(name, name2) != 0)) { err = CRYPT_INVALID_ARG; goto error; @@ -163,7 +163,7 @@ int ecc_verify_hash_ex(const unsigned char *sig, unsigned long siglen, /* for curves with a == -3 keep ma == NULL */ if (mp_cmp(a_plus3, m) != LTC_MP_EQ) { - if ((err = mp_init_multi(&mu, &ma, NULL)) != CRYPT_OK) { goto error; } + if ((err = mp_init_multi(&mu, &ma, LTC_NULL)) != CRYPT_OK) { goto error; } if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; } if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; } } @@ -198,7 +198,7 @@ error: if (mQ != NULL) ltc_ecc_del_point(mQ); if (mu != NULL) mp_clear(mu); if (ma != NULL) mp_clear(ma); - mp_clear_multi(r, s, v, w, u1, u2, e, a_plus3, NULL); + mp_clear_multi(r, s, v, w, u1, u2, e, a_plus3, LTC_NULL); if (mp != NULL) mp_montgomery_free(mp); return err; } diff --git a/src/ltc/pk/ecc/ltc_ecc_import_point.c b/src/ltc/pk/ecc/ltc_ecc_import_point.c index 8ef31eaf..6250fca2 100644 --- a/src/ltc/pk/ecc/ltc_ecc_import_point.c +++ b/src/ltc/pk/ecc/ltc_ecc_import_point.c @@ -12,7 +12,7 @@ int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *pri void *t1, *t2; /* init key + temporary numbers */ - if (mp_init_multi(&t1, &t2, NULL) != CRYPT_OK) { + if (mp_init_multi(&t1, &t2, LTC_NULL) != CRYPT_OK) { return CRYPT_MEM; } @@ -54,7 +54,7 @@ int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *pri err = CRYPT_OK; cleanup: - mp_clear_multi(t1, t2, NULL); + mp_clear_multi(t1, t2, LTC_NULL); return err; } diff --git a/src/ltc/pk/ecc/ltc_ecc_is_point.c b/src/ltc/pk/ecc/ltc_ecc_is_point.c index db10232c..56a9537d 100644 --- a/src/ltc/pk/ecc/ltc_ecc_is_point.c +++ b/src/ltc/pk/ecc/ltc_ecc_is_point.c @@ -21,7 +21,7 @@ int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y) b = dp->B; a = dp->A; - if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) return err; + if ((err = mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) return err; /* compute y^2 */ if ((err = mp_sqr(y, t1)) != CRYPT_OK) goto cleanup; @@ -55,7 +55,7 @@ int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y) } cleanup: - mp_clear_multi(t1, t2, NULL); + mp_clear_multi(t1, t2, LTC_NULL); return err; } diff --git a/src/ltc/pk/ecc/ltc_ecc_is_point_at_infinity.c b/src/ltc/pk/ecc/ltc_ecc_is_point_at_infinity.c index 8a3e3857..2afc4d49 100644 --- a/src/ltc/pk/ecc/ltc_ecc_is_point_at_infinity.c +++ b/src/ltc/pk/ecc/ltc_ecc_is_point_at_infinity.c @@ -27,7 +27,7 @@ int ltc_ecc_is_point_at_infinity(const ecc_point *P, void *modulus, int *retval) } /* initialize */ - if ((err = mp_init_multi(&x3, &y2, NULL)) != CRYPT_OK) goto done; + if ((err = mp_init_multi(&x3, &y2, LTC_NULL)) != CRYPT_OK) goto done; /* compute y^2 */ if ((err = mp_mulmod(P->y, P->y, modulus, y2)) != CRYPT_OK) goto cleanup; @@ -45,7 +45,7 @@ int ltc_ecc_is_point_at_infinity(const ecc_point *P, void *modulus, int *retval) } cleanup: - mp_clear_multi(x3, y2, NULL); + mp_clear_multi(x3, y2, LTC_NULL); done: return err; } diff --git a/src/ltc/pk/ecc/ltc_ecc_map.c b/src/ltc/pk/ecc/ltc_ecc_map.c index ffe6f85d..163fb412 100644 --- a/src/ltc/pk/ecc/ltc_ecc_map.c +++ b/src/ltc/pk/ecc/ltc_ecc_map.c @@ -30,7 +30,7 @@ int ltc_ecc_map(ecc_point *P, void *modulus, void *mp) return ltc_ecc_set_point_xyz(0, 0, 1, P); } - if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) { return err; } @@ -55,7 +55,7 @@ int ltc_ecc_map(ecc_point *P, void *modulus, void *mp) err = CRYPT_OK; done: - mp_clear_multi(t1, t2, NULL); + mp_clear_multi(t1, t2, LTC_NULL); return err; } diff --git a/src/ltc/pk/ecc/ltc_ecc_points.c b/src/ltc/pk/ecc/ltc_ecc_points.c index 5700c0ed..b762db50 100644 --- a/src/ltc/pk/ecc/ltc_ecc_points.c +++ b/src/ltc/pk/ecc/ltc_ecc_points.c @@ -21,7 +21,7 @@ ecc_point *ltc_ecc_new_point(void) if (p == NULL) { return NULL; } - if (mp_init_multi(&p->x, &p->y, &p->z, NULL) != CRYPT_OK) { + if (mp_init_multi(&p->x, &p->y, &p->z, LTC_NULL) != CRYPT_OK) { XFREE(p); return NULL; } @@ -35,7 +35,7 @@ void ltc_ecc_del_point(ecc_point *p) { /* prevents free'ing null arguments */ if (p != NULL) { - mp_clear_multi(p->x, p->y, p->z, NULL); /* note: p->z may be NULL but that's ok with this function anyways */ + mp_clear_multi(p->x, p->y, p->z, LTC_NULL); /* note: p->z may be NULL but that's ok with this function anyways */ XFREE(p); } } diff --git a/src/ltc/pk/ecc/ltc_ecc_projective_add_point.c b/src/ltc/pk/ecc/ltc_ecc_projective_add_point.c index 71630338..448c2bb6 100644 --- a/src/ltc/pk/ecc/ltc_ecc_projective_add_point.c +++ b/src/ltc/pk/ecc/ltc_ecc_projective_add_point.c @@ -31,7 +31,7 @@ int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_poi LTC_ARGCHK(modulus != NULL); LTC_ARGCHK(mp != NULL); - if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, LTC_NULL)) != CRYPT_OK) { return err; } @@ -52,7 +52,7 @@ int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_poi if ((mp_cmp(P->x, Q->x) == LTC_MP_EQ) && (mp_cmp(P->z, Q->z) == LTC_MP_EQ)) { if (mp_cmp(P->y, Q->y) == LTC_MP_EQ) { /* here P = Q >> Result = 2 * P (use doubling) */ - mp_clear_multi(t1, t2, x, y, z, NULL); + mp_clear_multi(t1, t2, x, y, z, LTC_NULL); return ltc_ecc_projective_dbl_point(P, R, ma, modulus, mp); } if ((err = mp_sub(modulus, Q->y, t1)) != CRYPT_OK) { goto done; } @@ -190,7 +190,7 @@ int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_poi err = CRYPT_OK; done: - mp_clear_multi(t1, t2, x, y, z, NULL); + mp_clear_multi(t1, t2, x, y, z, LTC_NULL); return err; } diff --git a/src/ltc/pk/ecc/ltc_ecc_projective_dbl_point.c b/src/ltc/pk/ecc/ltc_ecc_projective_dbl_point.c index 6e01939c..c99a2674 100644 --- a/src/ltc/pk/ecc/ltc_ecc_projective_dbl_point.c +++ b/src/ltc/pk/ecc/ltc_ecc_projective_dbl_point.c @@ -47,7 +47,7 @@ int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, voi LTC_ARGCHK(modulus != NULL); LTC_ARGCHK(mp != NULL); - if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&t1, &t2, LTC_NULL)) != CRYPT_OK) { return err; } @@ -176,7 +176,7 @@ int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, voi err = CRYPT_OK; done: - mp_clear_multi(t2, t1, NULL); + mp_clear_multi(t2, t1, LTC_NULL); return err; } #endif diff --git a/src/ltc/pk/ed25519/ed25519_export.c b/src/ltc/pk/ed25519/ed25519_export.c index 36adfc9d..2b710e58 100644 --- a/src/ltc/pk/ed25519/ed25519_export.c +++ b/src/ltc/pk/ed25519/ed25519_export.c @@ -23,7 +23,7 @@ int ed25519_export( unsigned char *out, unsigned long *outlen, { LTC_ARGCHK(key != NULL); - if (key->algo != PKA_ED25519) return CRYPT_PK_INVALID_TYPE; + if (key->algo != LTC_OID_ED25519) return CRYPT_PK_INVALID_TYPE; return ec25519_export(out, outlen, which, key); } diff --git a/src/ltc/pk/ed25519/ed25519_import.c b/src/ltc/pk/ed25519/ed25519_import.c index 9684e6fa..f197d59d 100644 --- a/src/ltc/pk/ed25519/ed25519_import.c +++ b/src/ltc/pk/ed25519/ed25519_import.c @@ -25,9 +25,9 @@ int ed25519_import(const unsigned char *in, unsigned long inlen, curve25519_key LTC_ARGCHK(key != NULL); key_len = sizeof(key->pub); - if ((err = x509_decode_subject_public_key_info(in, inlen, PKA_ED25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) { + if ((err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_ED25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) { key->type = PK_PUBLIC; - key->algo = PKA_ED25519; + key->algo = LTC_OID_ED25519; } return err; } diff --git a/src/ltc/pk/ed25519/ed25519_import_pkcs8.c b/src/ltc/pk/ed25519/ed25519_import_pkcs8.c index 3137c512..71f12de4 100644 --- a/src/ltc/pk/ed25519/ed25519_import_pkcs8.c +++ b/src/ltc/pk/ed25519/ed25519_import_pkcs8.c @@ -22,7 +22,7 @@ int ed25519_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, curve25519_key *key) { - return ec25519_import_pkcs8(in, inlen, pwd, pwdlen, PKA_ED25519, tweetnacl_crypto_sk_to_pk, key); + return ec25519_import_pkcs8(in, inlen, pwd, pwdlen, LTC_OID_ED25519, tweetnacl_crypto_sk_to_pk, key); } #endif diff --git a/src/ltc/pk/ed25519/ed25519_import_raw.c b/src/ltc/pk/ed25519/ed25519_import_raw.c index 0a11372b..19955d13 100644 --- a/src/ltc/pk/ed25519/ed25519_import_raw.c +++ b/src/ltc/pk/ed25519/ed25519_import_raw.c @@ -32,7 +32,7 @@ int ed25519_import_raw(const unsigned char *in, unsigned long inlen, int which, } else { return CRYPT_INVALID_ARG; } - key->algo = PKA_ED25519; + key->algo = LTC_OID_ED25519; key->type = which; return CRYPT_OK; diff --git a/src/ltc/pk/ed25519/ed25519_import_x509.c b/src/ltc/pk/ed25519/ed25519_import_x509.c index 451c4704..44978ac2 100644 --- a/src/ltc/pk/ed25519/ed25519_import_x509.c +++ b/src/ltc/pk/ed25519/ed25519_import_x509.c @@ -31,13 +31,13 @@ int ed25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519 LTC_ARGCHK(key != NULL); if ((err = x509_decode_public_key_from_certificate(in, inlen, - PKA_ED25519, + LTC_OID_ED25519, LTC_ASN1_EOL, NULL, NULL, (public_key_decode_cb)s_ed25519_decode, key)) != CRYPT_OK) { return err; } key->type = PK_PUBLIC; - key->algo = PKA_ED25519; + key->algo = LTC_OID_ED25519; return err; } diff --git a/src/ltc/pk/ed25519/ed25519_make_key.c b/src/ltc/pk/ed25519/ed25519_make_key.c index 5d81e5ac..7cec1959 100644 --- a/src/ltc/pk/ed25519/ed25519_make_key.c +++ b/src/ltc/pk/ed25519/ed25519_make_key.c @@ -28,7 +28,7 @@ int ed25519_make_key(prng_state *prng, int wprng, curve25519_key *key) } key->type = PK_PRIVATE; - key->algo = PKA_ED25519; + key->algo = LTC_OID_ED25519; return err; } diff --git a/src/ltc/pk/ed25519/ed25519_sign.c b/src/ltc/pk/ed25519/ed25519_sign.c index 86a4ea23..d5bf364e 100644 --- a/src/ltc/pk/ed25519/ed25519_sign.c +++ b/src/ltc/pk/ed25519/ed25519_sign.c @@ -9,17 +9,10 @@ #ifdef LTC_CURVE25519 -/** - Create an Ed25519 signature. - @param private_key The private Ed25519 key in the pair - @param public_key The public Ed25519 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 ed25519_sign(const unsigned char *msg, unsigned long msglen, - unsigned char *sig, unsigned long *siglen, - const curve25519_key *private_key) +static int s_ed25519_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + const curve25519_key *private_key) { unsigned char *s; unsigned long long smlen; @@ -30,7 +23,7 @@ int ed25519_sign(const unsigned char *msg, unsigned long msglen, LTC_ARGCHK(siglen != NULL); LTC_ARGCHK(private_key != NULL); - if (private_key->algo != PKA_ED25519) return CRYPT_PK_INVALID_TYPE; + if (private_key->algo != LTC_OID_ED25519) return CRYPT_PK_INVALID_TYPE; if (private_key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; if (*siglen < 64uL) { @@ -44,7 +37,8 @@ int ed25519_sign(const unsigned char *msg, unsigned long msglen, err = tweetnacl_crypto_sign(s, &smlen, msg, msglen, - private_key->priv, private_key->pub); + private_key->priv, private_key->pub, + ctx, ctxlen); XMEMCPY(sig, s, 64uL); *siglen = 64uL; @@ -57,4 +51,76 @@ int ed25519_sign(const unsigned char *msg, unsigned long msglen, return err; } +/** + Create an Ed25519ctx signature. + @param msg The data to be signed + @param msglen [in] The size of the date to be signed + @param sig [out] The destination of the shared data + @param siglen [in/out] The max size and resulting size of the shared data. + @param ctx [in] The context is a constant null terminated string + @param private_key The private Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519ctx_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + const curve25519_key *private_key) +{ + int err; + unsigned char ctx_prefix[292]; + unsigned long ctx_prefix_size = sizeof(ctx_prefix); + + LTC_ARGCHK(ctx != NULL); + + if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0, ctx, ctxlen)) != CRYPT_OK) + return err; + + return s_ed25519_sign(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, private_key); +} + +/** + Create an Ed25519ph signature. + @param msg The data to be signed + @param msglen [in] The size of the date to be signed + @param sig [out] The destination of the shared data + @param siglen [in/out] The max size and resulting size of the shared data. + @param ctx [in] The context is a constant null terminated string + @param private_key The private Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519ph_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const unsigned char *ctx, unsigned long ctxlen, + const curve25519_key *private_key) +{ + int err; + unsigned char msg_hash[64]; + unsigned char ctx_prefix[292]; + unsigned long ctx_prefix_size = sizeof(ctx_prefix); + + if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1, ctx, ctxlen)) != CRYPT_OK) + return err; + + if ((err = tweetnacl_crypto_ph(msg_hash, msg, msglen)) != CRYPT_OK) + return err; + + return s_ed25519_sign(msg_hash, sizeof(msg_hash), sig, siglen, ctx_prefix, ctx_prefix_size, private_key); +} + +/** + Create an Ed25519 signature. + @param msg The data to be signed + @param msglen [in] The size of the date to be signed + @param sig [out] The destination of the shared data + @param siglen [in/out] The max size and resulting size of the shared data. + @param private_key The private Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519_sign(const unsigned char *msg, unsigned long msglen, + unsigned char *sig, unsigned long *siglen, + const curve25519_key *private_key) +{ + return s_ed25519_sign(msg, msglen, sig, siglen, NULL, 0, private_key); +} + #endif diff --git a/src/ltc/pk/ed25519/ed25519_verify.c b/src/ltc/pk/ed25519/ed25519_verify.c index d2c30c2c..e7dcc307 100644 --- a/src/ltc/pk/ed25519/ed25519_verify.c +++ b/src/ltc/pk/ed25519/ed25519_verify.c @@ -9,18 +9,11 @@ #ifdef LTC_CURVE25519 -/** - Verify an Ed25519 signature. - @param private_key The private Ed25519 key in the pair - @param public_key The public Ed25519 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. - @param stat [out] The result of the signature verification, 1==valid, 0==invalid - @return CRYPT_OK if successful -*/ -int ed25519_verify(const unsigned char *msg, unsigned long msglen, - const unsigned char *sig, unsigned long siglen, - int *stat, const curve25519_key *public_key) +static int s_ed25519_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const curve25519_key *public_key) { unsigned char* m; unsigned long long mlen; @@ -34,7 +27,7 @@ int ed25519_verify(const unsigned char *msg, unsigned long msglen, *stat = 0; if (siglen != 64uL) return CRYPT_INVALID_ARG; - if (public_key->algo != PKA_ED25519) return CRYPT_PK_INVALID_TYPE; + if (public_key->algo != LTC_OID_ED25519) return CRYPT_PK_INVALID_TYPE; mlen = msglen + siglen; if ((mlen < msglen) || (mlen < siglen)) return CRYPT_OVERFLOW; @@ -48,14 +41,94 @@ int ed25519_verify(const unsigned char *msg, unsigned long msglen, err = tweetnacl_crypto_sign_open(stat, m, &mlen, m, mlen, + ctx, ctxlen, public_key->pub); #ifdef LTC_CLEAN_STACK - zeromem(m, mlen); + zeromem(m, msglen + siglen); #endif XFREE(m); return err; } +/** + Verify an Ed25519ctx signature. + @param msg [in] The data to be verified + @param msglen [in] The size of the data to be verified + @param sig [in] The signature to be verified + @param siglen [in] The size of the signature to be verified + @param ctx [in] The context + @param ctxlen [in] The size of the context + @param stat [out] The result of the signature verification, 1==valid, 0==invalid + @param public_key [in] The public Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519ctx_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const curve25519_key *public_key) +{ + unsigned char ctx_prefix[292]; + unsigned long ctx_prefix_size = sizeof(ctx_prefix); + + LTC_ARGCHK(ctx != NULL); + + if (ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 0, ctx, ctxlen) != CRYPT_OK) + return CRYPT_INVALID_ARG; + + return s_ed25519_verify(msg, msglen, sig, siglen, ctx_prefix, ctx_prefix_size, stat, public_key); +} + +/** + Verify an Ed25519ph signature. + @param msg [in] The data to be verified + @param msglen [in] The size of the data to be verified + @param sig [in] The signature to be verified + @param siglen [in] The size of the signature to be verified + @param ctx [in] The context + @param ctxlen [in] The size of the context + @param stat [out] The result of the signature verification, 1==valid, 0==invalid + @param public_key [in] The public Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519ph_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + const unsigned char *ctx, unsigned long ctxlen, + int *stat, + const curve25519_key *public_key) +{ + int err; + unsigned char msg_hash[64]; + unsigned char ctx_prefix[292]; + unsigned long ctx_prefix_size = sizeof(ctx_prefix); + + if ((err = ec25519_crypto_ctx(ctx_prefix, &ctx_prefix_size, 1, ctx, ctxlen)) != CRYPT_OK) + return err; + + if ((err = tweetnacl_crypto_ph(msg_hash, msg, msglen)) != CRYPT_OK) + return err; + + return s_ed25519_verify(msg_hash, sizeof(msg_hash), sig, siglen, ctx_prefix, ctx_prefix_size, stat, public_key); +} + +/** + Verify an Ed25519 signature. + @param msg [in] The data to be verified + @param msglen [in] The size of the data to be verified + @param sig [in] The signature to be verified + @param siglen [in] The size of the signature to be verified + @param stat [out] The result of the signature verification, 1==valid, 0==invalid + @param public_key [in] The public Ed25519 key in the pair + @return CRYPT_OK if successful +*/ +int ed25519_verify(const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + int *stat, + const curve25519_key *public_key) +{ + return s_ed25519_verify(msg, msglen, sig, siglen, NULL, 0, stat, public_key); +} + #endif diff --git a/src/ltc/pk/pkcs1/pkcs_1_oaep_encode.c b/src/ltc/pk/pkcs1/pkcs_1_oaep_encode.c index 7a8d6d1b..171df053 100644 --- a/src/ltc/pk/pkcs1/pkcs_1_oaep_encode.c +++ b/src/ltc/pk/pkcs1/pkcs_1_oaep_encode.c @@ -33,7 +33,7 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, unsigned long hLen, x, y, modulus_len; int err; - LTC_ARGCHK(msg != NULL); + LTC_ARGCHK((msglen == 0) || (msg != NULL)); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); @@ -95,9 +95,11 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, /* 0x01 byte */ DB[x++] = 0x01; - /* message (length = msglen) */ - XMEMCPY(DB+x, msg, msglen); - x += msglen; + if (msglen != 0) { + /* message (length = msglen) */ + XMEMCPY(DB+x, msg, msglen); + x += msglen; + } /* now choose a random seed */ if (prng_descriptor[prng_idx].read(seed, hLen, prng) != hLen) { diff --git a/src/ltc/pk/pkcs1/pkcs_1_v1_5_decode.c b/src/ltc/pk/pkcs1/pkcs_1_v1_5_decode.c index c07d81f8..e9880607 100644 --- a/src/ltc/pk/pkcs1/pkcs_1_v1_5_decode.c +++ b/src/ltc/pk/pkcs1/pkcs_1_v1_5_decode.c @@ -58,7 +58,7 @@ int pkcs_1_v1_5_decode(const unsigned char *msg, } ps_len = i++ - 2; - if (i >= modulus_len) { + if (i > modulus_len) { /* There was no octet with hexadecimal value 0x00 to separate ps from m. */ result = CRYPT_INVALID_PACKET; diff --git a/src/ltc/pk/pkcs1/pkcs_1_v1_5_encode.c b/src/ltc/pk/pkcs1/pkcs_1_v1_5_encode.c index bb3436bf..a21df4bf 100644 --- a/src/ltc/pk/pkcs1/pkcs_1_v1_5_encode.c +++ b/src/ltc/pk/pkcs1/pkcs_1_v1_5_encode.c @@ -35,6 +35,10 @@ int pkcs_1_v1_5_encode(const unsigned char *msg, unsigned char *ps; int result; + LTC_ARGCHK((msglen == 0) || (msg != NULL)); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + /* valid block_type? */ if ((block_type != LTC_PKCS_1_EMSA) && (block_type != LTC_PKCS_1_EME)) { @@ -88,7 +92,9 @@ int pkcs_1_v1_5_encode(const unsigned char *msg, out[0] = 0x00; out[1] = (unsigned char)block_type; /* block_type 1 or 2 */ out[2 + ps_len] = 0x00; - XMEMCPY(&out[2 + ps_len + 1], msg, msglen); + if (msglen != 0) { + XMEMCPY(&out[2 + ps_len + 1], msg, msglen); + } *outlen = modulus_len; result = CRYPT_OK; diff --git a/src/ltc/pk/rsa/rsa_decrypt_key.c b/src/ltc/pk/rsa/rsa_decrypt_key.c index 34a11f91..8c6ca3d8 100644 --- a/src/ltc/pk/rsa/rsa_decrypt_key.c +++ b/src/ltc/pk/rsa/rsa_decrypt_key.c @@ -33,6 +33,7 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen int err; unsigned char *tmp; + LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); diff --git a/src/ltc/pk/rsa/rsa_encrypt_key.c b/src/ltc/pk/rsa/rsa_encrypt_key.c index 66942608..e0f91e19 100644 --- a/src/ltc/pk/rsa/rsa_encrypt_key.c +++ b/src/ltc/pk/rsa/rsa_encrypt_key.c @@ -34,7 +34,7 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, unsigned long modulus_bitlen, modulus_bytelen, x; int err; - LTC_ARGCHK(in != NULL); + LTC_ARGCHK((inlen == 0) || (in != NULL)); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(key != NULL); diff --git a/src/ltc/pk/rsa/rsa_export.c b/src/ltc/pk/rsa/rsa_export.c index ac8fed22..225224d0 100644 --- a/src/ltc/pk/rsa/rsa_export.c +++ b/src/ltc/pk/rsa/rsa_export.c @@ -78,7 +78,7 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, const rsa_ke } err = x509_encode_subject_public_key_info(out, outlen, - PKA_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0); + LTC_OID_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0); finish: if (tmp != out) XFREE(tmp); diff --git a/src/ltc/pk/rsa/rsa_import.c b/src/ltc/pk/rsa/rsa_import.c index 5efb125e..1240a77e 100644 --- a/src/ltc/pk/rsa/rsa_import.c +++ b/src/ltc/pk/rsa/rsa_import.c @@ -9,8 +9,74 @@ #ifdef LTC_MRSA + +/** + Import an RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only] + + The `key` passed into this function has to be already initialized and will + NOT be free'd on error! + + @param in The packet to import from + @param inlen It's length (octets) + @param key [out] Destination for newly imported key + @return CRYPT_OK if successful +*/ +int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + int err; + unsigned long version = -1; + + err = der_decode_sequence_multi(in, inlen, LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_EOL, 0UL, NULL); + + if (err == CRYPT_OVERFLOW) { + /* the version would fit into an LTC_ASN1_SHORT_INTEGER + * so we try to decode as a public key + */ + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) { + key->type = PK_PUBLIC; + } + goto LBL_OUT; + } else if (err != CRYPT_INPUT_TOO_LONG) { + /* couldn't decode the version, so error out */ + goto LBL_OUT; + } + + if (version == 0) { + /* it's a private key */ + if ((err = der_decode_sequence_multi(in, inlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_INTEGER, 1UL, key->d, + LTC_ASN1_INTEGER, 1UL, key->p, + LTC_ASN1_INTEGER, 1UL, key->q, + LTC_ASN1_INTEGER, 1UL, key->dP, + LTC_ASN1_INTEGER, 1UL, key->dQ, + LTC_ASN1_INTEGER, 1UL, key->qP, + LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { + goto LBL_OUT; + } + key->type = PK_PRIVATE; + } else if (version == 1) { + /* we don't support multi-prime RSA */ + err = CRYPT_PK_INVALID_TYPE; + goto LBL_OUT; + } + err = CRYPT_OK; +LBL_OUT: + return err; +} + /** - Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in PKCS #1 v2.1] + Import multiple formats of RSA public and private keys. + + RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only] + SubjectPublicKeyInfo formatted public keys + @param in The packet to import from @param inlen It's length (octets) @param key [out] Destination for newly imported key @@ -19,7 +85,6 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) { int err; - void *zero; unsigned char *tmpbuf=NULL; unsigned long tmpbuf_len, len; @@ -42,7 +107,7 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) len = 0; err = x509_decode_subject_public_key_info(in, inlen, - PKA_RSA, tmpbuf, &tmpbuf_len, + LTC_OID_RSA, tmpbuf, &tmpbuf_len, LTC_ASN1_NULL, NULL, &len); if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */ @@ -60,50 +125,9 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) } /* not SSL public key, try to match against PKCS #1 standards */ - err = der_decode_sequence_multi(in, inlen, LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_EOL, 0UL, NULL); - - if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { - goto LBL_ERR; - } - - if (mp_cmp_d(key->N, 0) == LTC_MP_EQ) { - if ((err = mp_init(&zero)) != CRYPT_OK) { - goto LBL_ERR; - } - /* it's a private key */ - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_INTEGER, 1UL, zero, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->e, - LTC_ASN1_INTEGER, 1UL, key->d, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->dP, - LTC_ASN1_INTEGER, 1UL, key->dQ, - LTC_ASN1_INTEGER, 1UL, key->qP, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - mp_clear(zero); - goto LBL_ERR; - } - mp_clear(zero); - key->type = PK_PRIVATE; - } else if (mp_cmp_d(key->N, 1) == LTC_MP_EQ) { - /* we don't support multi-prime RSA */ - err = CRYPT_PK_INVALID_TYPE; - goto LBL_ERR; - } else { - /* it's a public key and we lack e */ - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->e, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto LBL_ERR; - } - key->type = PK_PUBLIC; + if ((err = rsa_import_pkcs1(in, inlen, key)) == CRYPT_OK) { + goto LBL_FREE; } - err = CRYPT_OK; - goto LBL_FREE; LBL_ERR: rsa_free(key); diff --git a/src/ltc/pk/rsa/rsa_import_pkcs8.c b/src/ltc/pk/rsa/rsa_import_pkcs8.c index 5d0bb6d2..9e02585c 100644 --- a/src/ltc/pk/rsa/rsa_import_pkcs8.c +++ b/src/ltc/pk/rsa/rsa_import_pkcs8.c @@ -46,10 +46,9 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen, rsa_key *key) { int err; - void *zero, *iter; unsigned char *buf1 = NULL, *buf2 = NULL; unsigned long buf1len, buf2len; - unsigned long oid[16]; + unsigned long oid[16], version; const char *rsaoid; ltc_asn1_list alg_seq[2], top_seq[3]; ltc_asn1_list *l = NULL; @@ -61,7 +60,7 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen, LTC_ARGCHK(ltc_mp.name != NULL); /* get RSA alg oid */ - err = pk_get_oid(PKA_RSA, &rsaoid); + err = pk_get_oid(LTC_OID_RSA, &rsaoid); if (err != CRYPT_OK) { goto LBL_NOFREE; } /* alloc buffers */ @@ -72,9 +71,8 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen, buf2 = XMALLOC(buf2len); if (buf2 == NULL) { err = CRYPT_MEM; goto LBL_FREE1; } - if ((err = mp_init_multi(&zero, &iter, NULL)) != CRYPT_OK) { goto LBL_FREE2; } /* init key */ - if ((err = rsa_init(key)) != CRYPT_OK) { goto LBL_FREE3; } + if ((err = rsa_init(key)) != CRYPT_OK) { goto LBL_FREE2; } /* try to decode encrypted priv key */ if ((err = pkcs8_decode_flexi(in, inlen, passwd, passwdlen, &l)) != CRYPT_OK) { @@ -86,7 +84,7 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen, /* try to decode unencrypted priv key */ LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL); LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_NULL, NULL, 0UL); - LTC_SET_ASN1(top_seq, 0, LTC_ASN1_INTEGER, zero, 1UL); + LTC_SET_ASN1(top_seq, 0, LTC_ASN1_SHORT_INTEGER, &version, 1UL); LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL); LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, buf1, buf1len); err=der_decode_sequence(decrypted, decryptedlen, top_seq, 3UL); @@ -97,28 +95,17 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen, goto LBL_ERR; } - err = der_decode_sequence_multi(buf1, top_seq[2].size, - LTC_ASN1_INTEGER, 1UL, zero, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->e, - LTC_ASN1_INTEGER, 1UL, key->d, - LTC_ASN1_INTEGER, 1UL, key->p, - LTC_ASN1_INTEGER, 1UL, key->q, - LTC_ASN1_INTEGER, 1UL, key->dP, - LTC_ASN1_INTEGER, 1UL, key->dQ, - LTC_ASN1_INTEGER, 1UL, key->qP, - LTC_ASN1_EOL, 0UL, NULL); - if (err != CRYPT_OK) { goto LBL_ERR; } + if ((err = rsa_import_pkcs1(buf1, top_seq[2].size, key)) != CRYPT_OK) { + goto LBL_ERR; + } key->type = PK_PRIVATE; err = CRYPT_OK; - goto LBL_FREE3; + goto LBL_FREE2; LBL_ERR: rsa_free(key); -LBL_FREE3: - mp_clear_multi(iter, zero, NULL); - if (l) der_free_sequence_flexi(l); LBL_FREE2: + if (l) der_free_sequence_flexi(l); XFREE(buf2); LBL_FREE1: XFREE(buf1); diff --git a/src/ltc/pk/rsa/rsa_import_x509.c b/src/ltc/pk/rsa/rsa_import_x509.c index a66a2672..e921aae0 100644 --- a/src/ltc/pk/rsa/rsa_import_x509.c +++ b/src/ltc/pk/rsa/rsa_import_x509.c @@ -39,7 +39,7 @@ int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key) } if ((err = x509_decode_public_key_from_certificate(in, inlen, - PKA_RSA, LTC_ASN1_NULL, + LTC_OID_RSA, LTC_ASN1_NULL, NULL, NULL, (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) { rsa_free(key); diff --git a/src/ltc/pk/rsa/rsa_key.c b/src/ltc/pk/rsa/rsa_key.c index 48a1d8fd..2d0712f2 100644 --- a/src/ltc/pk/rsa/rsa_key.c +++ b/src/ltc/pk/rsa/rsa_key.c @@ -87,7 +87,7 @@ void rsa_shrink_key(rsa_key *key) int rsa_init(rsa_key *key) { LTC_ARGCHK(key != NULL); - return mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL); + return mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, LTC_NULL); } /** @@ -97,7 +97,7 @@ int rsa_init(rsa_key *key) void rsa_free(rsa_key *key) { LTC_ARGCHKVD(key != NULL); - mp_cleanup_multi(&key->q, &key->p, &key->qP, &key->dP, &key->dQ, &key->N, &key->d, &key->e, NULL); + mp_cleanup_multi(&key->q, &key->p, &key->qP, &key->dP, &key->dQ, &key->N, &key->d, &key->e, LTC_NULL); } #endif diff --git a/src/ltc/pk/rsa/rsa_make_key.c b/src/ltc/pk/rsa/rsa_make_key.c index e0402afd..6bfc0419 100644 --- a/src/ltc/pk/rsa/rsa_make_key.c +++ b/src/ltc/pk/rsa/rsa_make_key.c @@ -22,7 +22,7 @@ static int s_rsa_make_key(prng_state *prng, int wprng, int size, void *e, rsa_ke return err; } - if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, NULL)) != CRYPT_OK) { + if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, LTC_NULL)) != CRYPT_OK) { return err; } @@ -76,7 +76,7 @@ static int s_rsa_make_key(prng_state *prng, int wprng, int size, void *e, rsa_ke errkey: rsa_free(key); cleanup: - mp_clear_multi(tmp2, tmp1, q, p, NULL); + mp_clear_multi(tmp2, tmp1, q, p, LTC_NULL); return err; } diff --git a/src/ltc/pk/rsa/rsa_verify_hash.c b/src/ltc/pk/rsa/rsa_verify_hash.c index ca4cdf9c..d946a202 100644 --- a/src/ltc/pk/rsa/rsa_verify_hash.c +++ b/src/ltc/pk/rsa/rsa_verify_hash.c @@ -136,7 +136,7 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long sigle LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen); - if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) { + if (der_decode_sequence_strict(out, outlen, siginfo, 2) != CRYPT_OK) { /* fallback to Legacy:missing NULL */ LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 1); if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) { diff --git a/src/ltc/pk/x25519/x25519_export.c b/src/ltc/pk/x25519/x25519_export.c index c828512b..0687c135 100644 --- a/src/ltc/pk/x25519/x25519_export.c +++ b/src/ltc/pk/x25519/x25519_export.c @@ -23,7 +23,7 @@ int x25519_export( unsigned char *out, unsigned long *outlen, { LTC_ARGCHK(key != NULL); - if (key->algo != PKA_X25519) return CRYPT_PK_INVALID_TYPE; + if (key->algo != LTC_OID_X25519) return CRYPT_PK_INVALID_TYPE; return ec25519_export(out, outlen, which, key); } diff --git a/src/ltc/pk/x25519/x25519_import.c b/src/ltc/pk/x25519/x25519_import.c index ddbbd54b..247885f9 100644 --- a/src/ltc/pk/x25519/x25519_import.c +++ b/src/ltc/pk/x25519/x25519_import.c @@ -25,9 +25,9 @@ int x25519_import(const unsigned char *in, unsigned long inlen, curve25519_key * LTC_ARGCHK(key != NULL); key_len = sizeof(key->pub); - if ((err = x509_decode_subject_public_key_info(in, inlen, PKA_X25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) { + if ((err = x509_decode_subject_public_key_info(in, inlen, LTC_OID_X25519, key->pub, &key_len, LTC_ASN1_EOL, NULL, 0uL)) == CRYPT_OK) { key->type = PK_PUBLIC; - key->algo = PKA_X25519; + key->algo = LTC_OID_X25519; } return err; } diff --git a/src/ltc/pk/x25519/x25519_import_pkcs8.c b/src/ltc/pk/x25519/x25519_import_pkcs8.c index 878df8cd..8b577c31 100644 --- a/src/ltc/pk/x25519/x25519_import_pkcs8.c +++ b/src/ltc/pk/x25519/x25519_import_pkcs8.c @@ -22,7 +22,7 @@ int x25519_import_pkcs8(const unsigned char *in, unsigned long inlen, const void *pwd, unsigned long pwdlen, curve25519_key *key) { - return ec25519_import_pkcs8(in, inlen, pwd, pwdlen, PKA_X25519, tweetnacl_crypto_scalarmult_base, key); + return ec25519_import_pkcs8(in, inlen, pwd, pwdlen, LTC_OID_X25519, tweetnacl_crypto_scalarmult_base, key); } #endif diff --git a/src/ltc/pk/x25519/x25519_import_raw.c b/src/ltc/pk/x25519/x25519_import_raw.c index d118e341..e86e8c6a 100644 --- a/src/ltc/pk/x25519/x25519_import_raw.c +++ b/src/ltc/pk/x25519/x25519_import_raw.c @@ -32,7 +32,7 @@ int x25519_import_raw(const unsigned char *in, unsigned long inlen, int which, c } else { return CRYPT_INVALID_ARG; } - key->algo = PKA_X25519; + key->algo = LTC_OID_X25519; key->type = which; return CRYPT_OK; diff --git a/src/ltc/pk/x25519/x25519_import_x509.c b/src/ltc/pk/x25519/x25519_import_x509.c index 18e0b67d..043b6ad9 100644 --- a/src/ltc/pk/x25519/x25519_import_x509.c +++ b/src/ltc/pk/x25519/x25519_import_x509.c @@ -31,13 +31,13 @@ int x25519_import_x509(const unsigned char *in, unsigned long inlen, curve25519_ LTC_ARGCHK(key != NULL); if ((err = x509_decode_public_key_from_certificate(in, inlen, - PKA_X25519, + LTC_OID_X25519, LTC_ASN1_EOL, NULL, NULL, (public_key_decode_cb)s_x25519_decode, key)) != CRYPT_OK) { return err; } key->type = PK_PUBLIC; - key->algo = PKA_X25519; + key->algo = LTC_OID_X25519; return err; } diff --git a/src/ltc/pk/x25519/x25519_make_key.c b/src/ltc/pk/x25519/x25519_make_key.c index 610eb96f..40276fe9 100644 --- a/src/ltc/pk/x25519/x25519_make_key.c +++ b/src/ltc/pk/x25519/x25519_make_key.c @@ -34,7 +34,7 @@ int x25519_make_key(prng_state *prng, int wprng, curve25519_key *key) tweetnacl_crypto_scalarmult_base(key->pub, key->priv); key->type = PK_PRIVATE; - key->algo = PKA_X25519; + key->algo = LTC_OID_X25519; return err; } |