fixed a couple of minor issues.

announcing the first release of simple-ASCON
This commit is contained in:
polfosol
2025-01-05 20:25:45 +03:30
parent 4e83264a6a
commit 7956dce4c1
25 changed files with 1316 additions and 1247 deletions

View File

@@ -2,7 +2,10 @@
**A minimalist ANSI-C compatible API for the AES encryption and block cipher modes**.
[![this](https://img.shields.io/badge/%C2%B5AES-white.png?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAFGklEQVR42r1XA5RjSxD9Wtu2bWX2e23btm3btm17Nxpmx8zYiK3XLzO/6vz0nuxb7yQ759xJ0l1V93Z1tX762r+cnJyCFoulJnxWART5Cvu8n+n+atLShJBlgCCi1WrtsbEpbHx8CnzXQZsUsAtEVef6sSzb12w1m6FfAXgIv/tgO8MwF+C3HuAL2Avxy3ySHIynEr1eyW7dKrB37ChlW7fOBuRQ2D084sjcuXwik8mA4AAEy099IbhXlVlV/POMzqPusb2HAAltNlsjaZo0Fdp0xSYVi3wc+DgEOCZ9bNS/QMc5wucHs+3apSLZZ9GmjZ5cveoDJBLwLQm+zcOTwxN/G/VbNiBnzvk5KGAFiDzRbWs3AbYBbCmKlEywr8zlx/QdJvfvSyA4gwRfiWx240Yk8gEB5ztt7kSJTHKdXA6jb6A1apUweg22N17S2AtsH3yMfCATEhIDAU1cEjuPF0tGjhSSceP49n/+CYE2O8fGjsJ1Zp2JErVZ1UYEgq4B5q25uUaEbQhMPwjo9kHqoTGcdOoU+F7gtm0zyNOnflh0IPAQFh6OlISERENtRL1n2727ZO2NtWJKJIwQRoHtn4AonHdsKzKhSDTEiUW+9wSgIfH2DuPMr46Ni0uCvgVcB6x0VqPJYni8eGpP9u8XlZteLgiJik4oiuRhaPcs+FkYFbXo0iIhtC/CGFwBe8iMGQJnATiv2P6ZlTKdvHz5LmMmiV84kLBIVGF6hUDozzKajRn4nQp44P8A0/8CBpSHK+CJvVOnIOfCIqmpGWBY6TP7xG/Eas2A1ZKFPno/LxyplZLlH5s/Jf+Y/Jn0NwLqQ2+wGPTgW4wrQGz/448op/RroS3zI7xcv5dQlMHoQ+bP548/Oh5XgJ0S4pRg0RUcVzABfzdf1lwMPne4IykGjTFY6c7zD20qwLYvIAKLj64Ext8/qvKMyv604KA/C7DLxtiU/HB+ZKIsEX//4UxeGBqi2ePHxbipOE0Bw/bv7/01AD+5Q7QxPjYkDsgJClhxbYUIC5hOF9RES/jN4xbSHPbECTEGyDXGjRMO3DuQ75hrncagUQBxiS/N4Wpa/bmFOdA/Kt/ofFko4M+NfwphCZ5Gjh8igPz9d/DeJ3u9kRyQHZAQEA/ZbfXjBJw/74UVT/cAPAExvisFMOzAgV7s8OHcYsXtWuEv9Y6iJ+CBpwd8IP1jXSqAPH7sj2se0nqdjYjA5Wp51zdvHt9jnYfQsflkmS1mPGoLuE5Au3YpMKI4CPqrw+cZ6dFDQjcsVWxEfJ5ReQwoYPC+wXzo34l2LhMAJCpiMOC2XN7h85bufriEeWt5QiQHkISshAyr1VrLtQIAZM0aPJg2OE7ChJTU2DTy4IHEpFKo6dYL6U+HKUqksV1bhKtWYWqXQxYKAYkJDxrcanc92uWF5Ihpp6bxoe+yWwSQmzd9YeQD8HbjG+sb3XJFSzGS0ttPwfEF4+HqlQoCy7pFgF0qjYe5rYPnBpIhqRPo5XM5xnSHAAuc+wxeQOC+z+ClkiPAqNAp5Dh69wiAjQangGRmKrpv7y4oMblEhLOAdqvb4eXzEsZziwAKMnq06Ib3Nf+qs6u+LTu1bDAV4CX1wnPfw+0CEHgTZqOjEyvP+v/SUWZKGbzjBX/3+w8rm0gkEfQt8DUgly550zo4zT8twWfc9/LTLOxjMzOziL9/5NeAzcjAa5UyWZEsg88AfBe64iVcAp/fX4ka+E4AlAH8lhve/wC9phuOb7e8lwAAAABJRU5ErkJggg==)](../../ "µAES") ![C](https://img.shields.io/badge/langauge-C-blue.svg) [![version](https://img.shields.io/badge/version-1.9.3-blue)](../../../../user-attachments/files/18098067/micro_aes-v1.9.3.zip "µAES-v1.9.3.zip") [![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![this](https://img.shields.io/badge/%C2%B5AES-white.png?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAFGklEQVR42r1XA5RjSxD9Wtu2bWX2e23btm3btm17Nxpmx8zYiK3XLzO/6vz0nuxb7yQ759xJ0l1V93Z1tX762r+cnJyCFoulJnxWART5Cvu8n+n+atLShJBlgCCi1WrtsbEpbHx8CnzXQZsUsAtEVef6sSzb12w1m6FfAXgIv/tgO8MwF+C3HuAL2Avxy3ySHIynEr1eyW7dKrB37ChlW7fOBuRQ2D084sjcuXwik8mA4AAEy099IbhXlVlV/POMzqPusb2HAAltNlsjaZo0Fdp0xSYVi3wc+DgEOCZ9bNS/QMc5wucHs+3apSLZZ9GmjZ5cveoDJBLwLQm+zcOTwxN/G/VbNiBnzvk5KGAFiDzRbWs3AbYBbCmKlEywr8zlx/QdJvfvSyA4gwRfiWx240Yk8gEB5ztt7kSJTHKdXA6jb6A1apUweg22N17S2AtsH3yMfCATEhIDAU1cEjuPF0tGjhSSceP49n/+CYE2O8fGjsJ1Zp2JErVZ1UYEgq4B5q25uUaEbQhMPwjo9kHqoTGcdOoU+F7gtm0zyNOnflh0IPAQFh6OlISERENtRL1n2727ZO2NtWJKJIwQRoHtn4AonHdsKzKhSDTEiUW+9wSgIfH2DuPMr46Ni0uCvgVcB6x0VqPJYni8eGpP9u8XlZteLgiJik4oiuRhaPcs+FkYFbXo0iIhtC/CGFwBe8iMGQJnATiv2P6ZlTKdvHz5LmMmiV84kLBIVGF6hUDozzKajRn4nQp44P8A0/8CBpSHK+CJvVOnIOfCIqmpGWBY6TP7xG/Eas2A1ZKFPno/LxyplZLlH5s/Jf+Y/Jn0NwLqQ2+wGPTgW4wrQGz/448op/RroS3zI7xcv5dQlMHoQ+bP548/Oh5XgJ0S4pRg0RUcVzABfzdf1lwMPne4IykGjTFY6c7zD20qwLYvIAKLj64Ext8/qvKMyv604KA/C7DLxtiU/HB+ZKIsEX//4UxeGBqi2ePHxbipOE0Bw/bv7/01AD+5Q7QxPjYkDsgJClhxbYUIC5hOF9RES/jN4xbSHPbECTEGyDXGjRMO3DuQ75hrncagUQBxiS/N4Wpa/bmFOdA/Kt/ofFko4M+NfwphCZ5Gjh8igPz9d/DeJ3u9kRyQHZAQEA/ZbfXjBJw/74UVT/cAPAExvisFMOzAgV7s8OHcYsXtWuEv9Y6iJ+CBpwd8IP1jXSqAPH7sj2se0nqdjYjA5Wp51zdvHt9jnYfQsflkmS1mPGoLuE5Au3YpMKI4CPqrw+cZ6dFDQjcsVWxEfJ5ReQwoYPC+wXzo34l2LhMAJCpiMOC2XN7h85bufriEeWt5QiQHkISshAyr1VrLtQIAZM0aPJg2OE7ChJTU2DTy4IHEpFKo6dYL6U+HKUqksV1bhKtWYWqXQxYKAYkJDxrcanc92uWF5Ihpp6bxoe+yWwSQmzd9YeQD8HbjG+sb3XJFSzGS0ttPwfEF4+HqlQoCy7pFgF0qjYe5rYPnBpIhqRPo5XM5xnSHAAuc+wxeQOC+z+ClkiPAqNAp5Dh69wiAjQangGRmKrpv7y4oMblEhLOAdqvb4eXzEsZziwAKMnq06Ib3Nf+qs6u+LTu1bDAV4CX1wnPfw+0CEHgTZqOjEyvP+v/SUWZKGbzjBX/3+w8rm0gkEfQt8DUgly550zo4zT8twWfc9/LTLOxjMzOziL9/5NeAzcjAa5UyWZEsg88AfBe64iVcAp/fX4ka+E4AlAH8lhve/wC9phuOb7e8lwAAAABJRU5ErkJggg==)](../../ "µAES")
![C](https://img.shields.io/badge/langauge-C-blue.svg)
[![version](https://img.shields.io/badge/version-1.11.0-blue)](../../../../user-attachments/files/22698833/micro_aes-v1.11.0.zip "µAES-v1.11.0.zip")
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
This is a highly flexible, small and portable implementation of most of the AES related algorithms.
@@ -31,7 +34,7 @@ and furthermore, authentication APIs for
* <font size="4">Clear and readable code</font> — written in a layman-friendly way with lots of comments to clarify its purpose. Also the code styling is a bit different, and IMHO more eye-catching, than what you might see in other implementations.
* <font size="4">Flexible</font> — most features are controllable by macros, so that you can just pick up what you need and disable the unnecessary parts. These [macros](micro_aes.h#L546) are defined in the header file and comments are added for each of them to explain what they represent. *Please read [those comments](micro_aes.h#L483) carefully before using the code*.
* <font size="4">Flexible</font> — most features are controllable by macros, so that you can just pick up what you need and disable the unnecessary parts. These [macros](micro_aes.h#L544) are defined in the header file and comments are added for each of them to explain what they represent. *Please read [those comments](micro_aes.h#L481) carefully before using the code*.
* <font size="4">Lightweight</font> — the API has very little memory footprint and compiled code size. The amount of RAM used by the functions doesn't exceed a few hundred bytes in most extreme cases. Moreover, the ROM space of µAES is optimized as much as possible.
@@ -53,7 +56,7 @@ and furthermore, authentication APIs for
* <font size="4">Portable</font> — µAES is fully compliant with the ANSI-C or C89 standard which, combined with its small size and independence from external libraries, makes it a competent candidate for embedded systems and mini applications.
You can even compile it with [Tiny C Compiler](https://bellard.org/tcc/):
You can even [compile it](../../../../user-attachments/files/21704976/TCPROJ.zip "instructions and prerequisites") with a vintage [Borland Turbo C](https://hackaday.com/2023/04/08/revisiting-borland-turbo-c-and-c/) or a teeny [tiny C compiler](https://bellard.org/tcc/):
```
path/to/tcc.exe -c micro_aes.c
path/to/tcc.exe micro_aes.c -run main.c

178
main.c
View File

@@ -2,7 +2,7 @@
==============================================================================
Name : main.c
Author : polfosol
Version : 10
Version : 11
Copyright : copyright © 2022 - polfosol
Description : test vectors for µAES ™ library, mostly generated by Crypto++ ®
==============================================================================
@@ -42,7 +42,7 @@ static const char
"3f9c56525efbe64a 876ad1d761d3fc93 59fb4f5b2354acd4 90",
*ofbcipher = "edab3105e673bc9e b9102539a9f457bc d28c8e4c92995f5c d9426926be1e775d"
"e22b8ce4d0278b18 181b8bec93b9726f 959aa5d701d46102 f0",
#if CTR_IV_LENGTH == 16
#if PRESET_COUNTER
*ctrcipher = "edab3105e673bc9e b9102539a9f457bc f2e2606dfa3f93c5 c51b910a89cddb67"
"191a118531ea0427 97626c9bfd370426 fdf3f59158bf7d4d 43",
#else
@@ -108,7 +108,7 @@ static void hex2bytes(const char* hex, uint8_t* bytes)
static void check(const char* method, void* result, const void* expected, size_t size)
{
int c = memcmp(expected, result, size);
printf("AES-%d %s: %s\n", AES_KEY_SIZE * 8, method, c ? "FAILED :`(" : "PASSED!");
printf("AES-%d %s: %s\n", AES_KEYLENGTH * 8, method, c ? "FAILED :`(" : "PASSED!");
memset(result, 0xcc, TAGGED);
}
@@ -124,7 +124,7 @@ int main(void)
#if MICRO_RJNDL
hex2bytes(iVec, input + 48);
hex2bytes(secondKey, test);
a = AES_KEY_SIZE == 16 ? key : input + (AES___ - 192) / 2;
a = AES_KEYLENGTH == 16 ? key : input + (AES_KEYLENGTH - 24) * 4;
AES_Cipher(test, 'E', authKey, output);
AES_Cipher(authKey, 'E', test, output + 16);
@@ -136,108 +136,108 @@ int main(void)
#endif
printf("%s %s Test results\n", __DATE__, __TIME__);
#if ECB && AES_KEY_SIZE - 8 * AES_PADDING == 16
#if ECB && AES___ == 64 * (AES_PADDING ^ 2)
hex2bytes(ecbcipher, test);
AES_ECB_encrypt(key, input, sp, output);
check("ECB encryption", output, test, sizeof input);
AES_ECB_decrypt(key, test, sizeof input, output);
check("ECB decryption", output, input, sp);
#endif
#if CBC && AES_KEY_SIZE == 16
#if CBC && AES___ == 128
hex2bytes(cbccipher, test);
AES_CBC_encrypt(key, iv, input, sp, output);
check("CBC encryption", output, test, CTS ? sp : sizeof input);
AES_CBC_decrypt(key, iv, test, CTS ? sp : sizeof input, output);
check("CBC decryption", output, input, sp);
#endif
#if CFB && AES_KEY_SIZE == 16
#if CFB && AES___ == 128
hex2bytes(cfbcipher, test);
AES_CFB_encrypt(key, iv, input, sp, output);
check("CFB encryption", output, test, sp);
AES_CFB_decrypt(key, iv, test, sp, output);
check("CFB decryption", output, input, sp);
#endif
#if OFB && AES_KEY_SIZE == 16
#if OFB && AES___ == 128
hex2bytes(ofbcipher, test);
AES_OFB_encrypt(key, iv, input, sp, output);
check("OFB encryption", output, test, sp);
AES_OFB_decrypt(key, iv, test, sp, output);
check("OFB decryption", output, input, sp);
#endif
#if CTR_NA && AES_KEY_SIZE == 16
#if CTR_NA && AES___ == 128
hex2bytes(ctrcipher, test);
AES_CTR_encrypt(key, iv, input, sp, output);
check("CTR encryption", output, test, sp);
AES_CTR_decrypt(key, iv, test, sp, output);
check("CTR decryption", output, input, sp);
#endif
#if XTS && AES_KEY_SIZE != 24
#if XTS && AES___ != 192
hex2bytes(xtscipher, test);
AES_XTS_encrypt(key, iv, input, sp, output);
check("XTS encryption", output, test, sp);
AES_XTS_decrypt(key, iv, test, sp, output);
check("XTS decryption", output, input, sp);
#endif
#if CMAC && AES_KEY_SIZE == 16
#if CMAC && AES___ == 128
hex2bytes(ptxt_cmac, test);
AES_CMAC(key, input, sp, output);
check("plaintext CMAC", output, test, 16);
#endif
#if POLY1305 && AES_KEY_SIZE == 16
#if POLY1305 && AES___ == 128
hex2bytes(poly_1305, test);
AES_Poly1305(key, iv, input, sp, output);
check("Poly-1305 *mac", output, test, 16);
check("Poly1305 of PT", output, test, 16);
#endif
#if GCM && AES_KEY_SIZE != 24
#if GCM && AES___ != 192
hex2bytes(gcmcipher, test);
AES_GCM_encrypt(key, iv, input, sp, a, sa, output, output + sp);
check("GCM encryption", output, test, sp + 16);
AES_GCM_decrypt(key, iv, test, sp, a, sa, 16, output);
AES_GCM_encrypt(key, iv, a, sa, input, sp, output);
check("GCM encryption", output, test, sp + GCM_TAG_LEN);
AES_GCM_decrypt(key, iv, a, sa, test, sp, output);
check("GCM decryption", output, input, sp);
#endif
#if CCM && AES_KEY_SIZE == 16
#if CCM && AES___ == 128
hex2bytes(ccmcipher, test);
AES_CCM_encrypt(key, iv, input, sp, a, sa, output, output + sp);
AES_CCM_encrypt(key, iv, a, sa, input, sp, output);
check("CCM encryption", output, test, sp + CCM_TAG_LEN);
*output ^= AES_CCM_decrypt(key, iv, test, sp, a, sa, CCM_TAG_LEN, output);
*output ^= AES_CCM_decrypt(key, iv, a, sa, test, sp, output);
check("CCM decryption", output, input, sp);
#endif
#if OCB && AES_KEY_SIZE == 16
#if OCB && AES___ == 128
hex2bytes(ocbcipher, test);
AES_OCB_encrypt(key, iv, input, sp, a, sa, output, output + sp);
AES_OCB_encrypt(key, iv, a, sa, input, sp, output);
check("OCB encryption", output, test, sp + OCB_TAG_LEN);
*output ^= AES_OCB_decrypt(key, iv, test, sp, a, sa, OCB_TAG_LEN, output);
*output ^= AES_OCB_decrypt(key, iv, a, sa, test, sp, output);
check("OCB decryption", output, input, sp);
#endif
#if SIV && AES_KEY_SIZE == 16
#if SIV && AES___ == 128
hex2bytes(sivcipher, test);
AES_SIV_encrypt(key, input, sp, a, sa, output, output + 16);
AES_SIV_encrypt(key, a, sa, input, sp, output, output + 16);
check("SIV encryption", output, test, sp + 16);
*output ^= AES_SIV_decrypt(key, test, test + 16, sp, a, sa, output);
*output ^= AES_SIV_decrypt(key, test, a, sa, test + 16, sp, output);
check("SIV decryption", output, input, sp);
#endif
#if GCM_SIV && AES_KEY_SIZE == 16
#if GCM_SIV && AES___ == 128
hex2bytes(gsvcipher, test);
GCM_SIV_encrypt(key, iv, input, sp, a, sa, output, output + sp);
check("GCMSIV encrypt", output, test, sp + 16);
*output ^= GCM_SIV_decrypt(key, iv, test, sp, a, sa, 16, output);
GCM_SIV_encrypt(key, iv, a, sa, input, sp, output);
check("GCMSIV encrypt", output, test, sp + SIVGCM_TAG_LEN);
*output ^= GCM_SIV_decrypt(key, iv, a, sa, test, sp, output);
check("GCMSIV decrypt", output, input, sp);
#endif
#if EAX && AES_KEY_SIZE == 16
#if EAX && AES___ == 128
hex2bytes(eaxcipher, test);
#if EAXP
AES_EAX_encrypt(key, a, input, sp, sa, output);
AES_EAX_encrypt(key, a, sa, input, sp, output);
check("EAX encryption", output, test, sp + 4);
AES_EAX_decrypt(key, a, test, sp, sa, output);
AES_EAX_decrypt(key, a, sa, test, sp, output);
#else
AES_EAX_encrypt(key, iv, input, sp, a, sa, output, output + sp);
check("EAX encryption", output, test, sp + 16);
AES_EAX_decrypt(key, iv, test, sp, a, sa, 16, output);
AES_EAX_encrypt(key, iv, a, sa, input, sp, output);
check("EAX encryption", output, test, sp + EAX_TAG_LEN);
AES_EAX_decrypt(key, iv, a, sa, test, sp, output);
#endif
check("EAX decryption", output, input, sp);
#endif
#if AES_KEY_SIZE + !FPE + CUSTOM_ALPHABET == 16
memcpy(test, fpecipher, FF_X == 3 ? (sp = 55) : sp);
#if FPE && AES___ == 128 && !CUSTOM_ALPHABET
memcpy(test, fpecipher, sp = FF_X == 3 ? 55 : PTSIZE);
#if FF_X == 3
AES_FPE_encrypt(key, a, fpe_plain, sp, output);
check("FF3 encryption", output, test, sp);
@@ -251,15 +251,15 @@ int main(void)
#endif
#if KWA
hex2bytes(k_wrapped, test);
AES_KEY_wrap(authKey, key + 32, AES_KEY_SIZE, output);
check("key wrapping ", output, test, AES_KEY_SIZE + 8);
AES_KEY_unwrap(authKey, test, AES_KEY_SIZE + 8, output);
check("key unwrapping", output, key + 32, AES_KEY_SIZE);
AES_KEY_wrap(authKey, key + 32, AES_KEYLENGTH, output);
check("KW- (key wrap)", output, test, AES_KEYLENGTH + 8);
AES_KEY_unwrap(authKey, test, AES_KEYLENGTH + 8, output);
check("key unwrapping", output, key + 32, AES_KEYLENGTH);
#endif
/** a template for "OFFICIAL TEST VECTORS": */
#if OCB * EAX * SIV * GCM_SIV * POLY1305 * FPE * (16 / AES_KEY_SIZE)
printf("+-> Let's do some extra tests\n");
if (AES_KEYLENGTH > 16) return 0;
printf("+-> Let's do some extra tests\n");
#if OCB
sp = sa = 24; /* taken from RFC-7253: */
hex2bytes("000102030405060708090A0B0C0D0E0F", key);
hex2bytes("BBAA99887766554433221107", iv);
@@ -267,33 +267,37 @@ int main(void)
hex2bytes("000102030405060708090A0B0C0D0E0F1011121314151617", input);
hex2bytes("1CA2207308C87C010756104D8840CE1952F09673A448A122\
C92C62241051F57356D7F3C90BB0E07F", test);
AES_OCB_encrypt(key, iv, input, sp, a, sa, output, output + sp);
AES_OCB_encrypt(key, iv, a, sa, input, sp, output);
check("OCB encryption", output, test, sp + OCB_TAG_LEN);
*output ^= AES_OCB_decrypt(key, iv, test, sp, a, sa, OCB_TAG_LEN, output);
*output += AES_OCB_decrypt(key, iv, a, sa, test, sp, output);
check("OCB decryption", output, input, sp);
#endif
#if GCM_SIV
sp = 11, sa = 7; /* taken from RFC-8452: */
hex2bytes("ee8e1ed9ff2540ae8f2ba9f50bc2f27c", key);
hex2bytes("752abad3e0afb5f434dc4310", iv);
hex2bytes("6578616d706c65", a);
hex2bytes("48656c6c6f20776f726c64", input);
hex2bytes("5d349ead175ef6b1def6fd4fbcdeb7e4793f4a1d7e4faa70100af1", test);
GCM_SIV_encrypt(key, iv, input, sp, a, sa, output, output + sp);
GCM_SIV_encrypt(key, iv, a, sa, input, sp, output);
check("GCMSIV encrypt", output, test, sp + 16);
*output ^= GCM_SIV_decrypt(key, iv, test, sp, a, sa, 16, output);
*output += GCM_SIV_decrypt(key, iv, a, sa, test, sp, output);
check("GCMSIV decrypt", output, input, sp);
sp = 12, sa = 1; /* taken from RFC-8452: */
sp = 32, sa = 1; /* taken from RFC-8452: */
hex2bytes("01000000000000000000000000000000", key);
hex2bytes("030000000000000000000000", iv);
hex2bytes("01", a);
hex2bytes("020000000000000000000000", input);
hex2bytes("296c7889fd99f41917f4462008299c51\
02745aaa3a0c469fad9e075a", test);
GCM_SIV_encrypt(key, iv, input, sp, a, sa, output, output + sp);
hex2bytes("02000000000000000000000000000000\
03000000000000000000000000000000", input);
hex2bytes("620048ef3c1e73e57e02bb8562c416a3\
19e73e4caac8e96a1ecb2933145a1d71\
e6af6a7f87287da059a71684ed3498e1", test);
GCM_SIV_encrypt(key, iv, a, sa, input, sp, output);
check("GCMSIV encrypt", output, test, sp + 16);
*output ^= GCM_SIV_decrypt(key, iv, test, sp, a, sa, 16, output);
*output += GCM_SIV_decrypt(key, iv, a, sa, test, sp, output);
check("GCMSIV decrypt", output, input, sp);
#endif
#if SIV
sp = 14, sa = 24; /* taken from RFC-5297: */
hex2bytes("fffefdfc fbfaf9f8 f7f6f5f4 f3f2f1f0\
f0f1f2f3 f4f5f6f7 f8f9fafb fcfdfeff", key);
@@ -302,18 +306,19 @@ int main(void)
hex2bytes("11223344 55667788 99aabbcc ddee", input);
hex2bytes("85632d07 c6e8f37f 950acd32 0a2ecc93\
40c02b96 90c4dc04 daef7f6a fe5c", test);
AES_SIV_encrypt(key, input, sp, a, sa, output, output + 16);
AES_SIV_encrypt(key, a, sa, input, sp, output, output + 16);
check("SIV encryption", output, test, sp + 16);
*output ^= AES_SIV_decrypt(key, test, test + 16, sp, a, sa, output);
*output += AES_SIV_decrypt(key, test, a, sa, test + 16, sp, output);
check("SIV decryption", output, input, sp);
sp = 16, sa = 0; /* from miscreant on github: bit.ly/3ycgGB */
hex2bytes("fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", key);
hex2bytes("00112233445566778899aabbccddeeff", input);
hex2bytes("f304f912863e303d5b540e5057c7010c942ffaf45b0e5ca5fb9a56a5263bb065", test);
AES_SIV_encrypt(key, input, sp, a, sa, output, output + 16);
AES_SIV_encrypt(key, a, sa, input, sp, output, output + 16);
check("SIV encryption", output, test, sp + 16);
*output ^= AES_SIV_decrypt(key, test, test + 16, sp, a, sa, output);
*output += AES_SIV_decrypt(key, test, a, sa, test + 16, sp, output);
check("SIV decryption", output, input, sp);
#endif
#if EAXP
sp = 0, sa = 50; /* from Annex G of the IEEE Std. 1703-2012 */
hex2bytes("01020304050607080102030405060708", key);
@@ -322,10 +327,10 @@ int main(void)
7C86F7540116007B040248F3C2040330\
0005", input);
hex2bytes("515AE775", test);
AES_EAX_encrypt(key, input, NULL, sp, sa, output);
check("EAX encryption", output, test, sp + 4);
sp += AES_EAX_decrypt(key, input, test, sp, sa, output);
check("EAX decryption", output, input, sp);
AES_EAX_encrypt(key, input, sa, NULL, sp, output);
check("EAX\'encryption", output, test, sp + 4);
sp += AES_EAX_decrypt(key, input, sa, test, sp, output);
check("EAX\'decryption", output, input, sp);
sp = 28, sa = 65; /* from Moise-Beroset-Phinney-Burns paper: */
hex2bytes("10 20 30 40 50 60 70 80 90 a0 b0 c0 d0 e0 f0 00", authKey);
hex2bytes("a2 0e 06 0c 60 86 48 01 86 fc 2f 81 1c aa 4e 01\
@@ -337,44 +342,13 @@ int main(void)
30 30 30 30 30 30 00 00 03 30 00 01", input);
hex2bytes("9c f3 2c 7e c2 4c 25 0b e7 b0 74 9f ee e7 1a 22\
0d 0e ee 97 6e c2 3d bf 0c aa 08 ea 00 54 3e 66", key);
AES_EAX_encrypt(authKey, test, input, sp, sa, output);
check("EAX encryption", output, key, sp + 4);
AES_EAX_decrypt(authKey, test, key, sp, sa, output);
#else
sp = 12, sa = 8; /* from Bellare-Rogaway-Wagner 2004 paper: */
hex2bytes("BD8E6E11475E60B268784C38C62FEB22", key);
hex2bytes("6EAC5C93072D8E8513F750935E46DA1B", iv);
hex2bytes("D4482D1CA78DCE0F", a);
hex2bytes("4DE3B35C3FC039245BD1FB7D", input);
hex2bytes("835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F", test);
AES_EAX_encrypt(key, iv, input, sp, a, sa, output, output + sp);
check("EAX encryption", output, test, sp + 16);
AES_EAX_decrypt(key, iv, test, sp, a, sa, 16, output);
AES_EAX_encrypt(authKey, test, sa, input, sp, output);
check("EAX\'encryption", output, key, sp + 4);
AES_EAX_decrypt(authKey, test, sa, key, sp, output);
check("EAX\'decryption", output, input, sp);
#endif
check("EAX decryption", output, input, sp);
#if (FF_X != 3) * CUSTOM_ALPHABET == 3
sp = 19, sa = 11;
hex2bytes("2B 7E 15 16 28 AE D2 A6 AB F7 15 88 09 CF 4F 3C", key);
hex2bytes("37 37 37 37 70 71 72 73 37 37 37", a);
memcpy(input, "0123456789abcdefghi", sp);
memcpy(output, "a9tv40mll9kdu509eum", sp);
AES_FPE_encrypt(key, a, sa, input, sp, test);
check("FF1 encryption", test, output, sp);
AES_FPE_decrypt(key, a, sa, output, sp, test);
check("FF1 decryption", test, input, sp);
#elif FF_X * !CUSTOM_ALPHABET == 3
sp = 29; /* zero tweak works for both FF3 and FF3-1 */
hex2bytes("EF 43 59 D8 D5 80 AA 4F 7F 03 6D 6F 04 FC 6A 94", key);
hex2bytes("00 00 00 00 00 00 00 00", a);
memcpy(input, "89012123456789000000789000000", sp);
memcpy(output, "34695224821734535122613701434", sp);
AES_FPE_encrypt(key, a, input, sp, test);
check("FF3 encryption", test, output, sp);
AES_FPE_decrypt(key, a, output, sp, test);
check("FF3 decryption", test, input, sp);
#endif
sp = 32; /* ↓ from Daniel J. Bernstein's 2005 paper */
#if POLY1305
sp = 32; /* taken from D.J. Bernstein (2005) paper: */
hex2bytes("66 3c ea 19 0f fb 83 d8 95 93 f3 f4 76 b6 bc 24\
d7 e6 79 10 7e a2 6a db 8c af 66 52 d0 65 61 36", input);
hex2bytes("6a cb 5f 61 a7 17 6d d3 20 c5 c1 eb 2e dc dc 74\

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
==============================================================================
Name : micro_aes.h
Author : polfosol
Version : 10
Version : 11
Copyright : copyright © 2022 - polfosol
Description : μAES ™ is a minimalist all-in-one library for AES encryption
==============================================================================
@@ -72,7 +72,7 @@ AES block-cipher modes of operation. The following modes can be enabled/disabled
#define MICRO_RJNDL WTF /* none of above; just rijndael API. dude.., why? */
/**----------------------------------------------------------------------------
Refer to the bottom of this document for more information about these macros:
Parameters and MACROs; refer to the bottom of this document for more info:
-----------------------------------------------------------------------------*/
#if ECB || (CBC && !CTS) || (XEX && !XTS)
@@ -86,33 +86,47 @@ Refer to the bottom of this document for more information about these macros:
#if FPE
#define CUSTOM_ALPHABET 0 /* if disabled, use default alphabet (digits 0..9) */
#define FF_X 1 /* algorithm type: (1) for FF1, or (3) for FF3-1 */
#if FF_X == 3
#define FF3_TWEAK_LEN 7 /* if the old version of FF3: (8), else FF3-1: (7) */
#endif
enum constant_parameters_of_modes
{
#if FF_X == 3
FF3_TWEAK_LEN = 7, /* fixed for FF3-1. (LEN=8 in old version of FF3) */
#endif
#if CTR_NA
#define CTR_IV_LENGTH 12 /* for using the last 32 bits as counter */
#define CTR_STARTVALUE 1 /* recommended value according to the RFC-3686. */
CTR_START_VALUE = 1, /* Recommended by the RFC-3686 */
CTR_IV_LENGTH = 12, /* use the last 32 bits of block for counting */
#define PRESET_COUNTER 0 /* enable this macro if CTR_IV_LENGTH == 16 */
#endif
#if CCM
#define CCM_NONCE_LEN 11 /* for 32-bit count (since one byte is reserved). */
#define CCM_TAG_LEN 16 /* must be an even number in the range of 4..16 */
CCM_NONCE_LEN = 11, /* for 32-bit count (since one byte is reserved) */
CCM_TAG_LEN = 16, /* must be EVEN. at most 16 bytes in all modes */
#endif
#if GCM
#define GCM_NONCE_LEN 12 /* RECOMMENDED. but other values are supported. */
GCM_NONCE_LEN = 12, /* Recommended; but other values are supported. */
GCM_TAG_LEN = 16,
#endif
#if EAX && !EAXP
#define EAX_NONCE_LEN 16 /* no specified limit; can be arbitrarily large. */
#if GCM_SIV
SIVGCM_NONCE_LEN = 12, /* the only valid value recommended by RFC-8452 */
SIVGCM_TAG_LEN = 16, /* the only valid value recommended by RFC-8452 */
#endif
#if OCB
#define OCB_NONCE_LEN 12 /* RECOMMENDED. must be positive and less than 16. */
#define OCB_TAG_LEN 16 /* again, please see the bottom of this document! */
OCB_NONCE_LEN = 12, /* Recommended; must be positive and less than 16 */
OCB_TAG_LEN = 16,
#endif
#if EAX && !EAXP
EAX_NONCE_LEN = 16, /* no specified limit; can be arbitrarily large */
EAX_TAG_LEN = 16, /* more info at the bottom of this document. */
#endif
#if AES___ != 256 && AES___ != 192
AES_KEYLENGTH = 16 /*- fallback value for invalid or undefined AES___ */
#else
AES_KEYLENGTH = AES___ / 8
#endif
};
/**----------------------------------------------------------------------------
Since <stdint.h> is not a part of ANSI-C, we may need a 'trick' to use uint8_t
@@ -257,19 +271,19 @@ Main functions for SIV-AES block ciphering
-----------------------------------------------------------------------------*/
#if SIV
void AES_SIV_encrypt( const uint8_t* keys, /* encryption key pair */
const void* pntxt, /* plaintext input */
const size_t ptextLen, /* length of plaintext */
const void* aData, /* added authentication data */
const size_t aDataLen, /* length of AAD (auth. data) */
const void* pntxt, /* plaintext input */
const size_t ptextLen, /* length of plaintext */
uint8_t iv[16], /* synthesized initial-vector */
void* crtxt ); /* ciphertext result */
char AES_SIV_decrypt( const uint8_t* keys, /* decryption key pair */
const uint8_t iv[16], /* provided initial-vector */
const void* crtxt, /* ciphertext input */
const size_t crtxtLen, /* length of ciphertext */
const void* aData, /* added authentication data */
const size_t aDataLen, /* length of AAD (auth. data) */
const void* crtxt, /* ciphertext input */
const size_t crtxtLen, /* length of ciphertext */
void* pntxt ); /* plaintext result */
#endif /* SIV */
@@ -279,21 +293,19 @@ Main functions for GCM-AES block ciphering
#if GCM
void AES_GCM_encrypt( const uint8_t* key, /* encryption key */
const uint8_t* nonce, /* nonce or IV (init. vector) */
const uint8_t* pntxt, /* plaintext input */
const size_t ptextLen, /* length of plaintext */
const uint8_t* aData, /* added authentication data */
const void* aData, /* added authentication data */
const size_t aDataLen, /* length of AAD (auth. data) */
uint8_t* crtxt, /* ciphertext result */
uint8_t auTag[16] ); /* message authentication tag */
const void* pntxt, /* plaintext input */
const size_t ptextLen, /* length of plaintext */
void* crtxt ); /* ciphertext + auth. tag */
char AES_GCM_decrypt( const uint8_t* key, /* decryption key */
const uint8_t* nonce, /* nonce or IV (init. vector) */
const uint8_t* crtxt, /* ciphertext + appended tag */
const size_t crtxtLen, /* length of ciphertext */
const uint8_t* aData, /* added authentication data */
const void* aData, /* added authentication data */
const size_t aDataLen, /* length of AAD (auth. data) */
const uint8_t tagLen, /* length of tag (if any) */
uint8_t* pntxt ); /* plaintext result */
const void* crtxt, /* ciphertext + appended tag */
const size_t crtxtLen, /* length of ciphertext */
void* pntxt ); /* plaintext result */
#endif /* GCM */
/**----------------------------------------------------------------------------
@@ -302,21 +314,19 @@ Main functions for CCM-AES block ciphering
#if CCM
void AES_CCM_encrypt( const uint8_t* key, /* encryption key */
const uint8_t* nonce, /* nonce or IV (init. vector) */
const uint8_t* pntxt, /* plaintext input */
const size_t ptextLen, /* length of plaintext */
const uint8_t* aData, /* added authentication data */
const void* aData, /* added authentication data */
const size_t aDataLen, /* length of AAD (auth. data) */
uint8_t* crtxt, /* ciphertext result */
uint8_t* auTag ); /* message authentication tag */
const void* pntxt, /* plaintext input */
const size_t ptextLen, /* length of plaintext */
void* crtxt ); /* ciphertext + auth. tag */
char AES_CCM_decrypt( const uint8_t* key, /* decryption key */
const uint8_t* nonce, /* nonce or IV (init. vector) */
const uint8_t* crtxt, /* ciphertext + appended tag */
const size_t crtxtLen, /* length of ciphertext */
const uint8_t* aData, /* added authentication data */
const void* aData, /* added authentication data */
const size_t aDataLen, /* length of AAD (auth. data) */
const uint8_t tagLen, /* length of tag (=CCM_TAG_LEN) */
uint8_t* pntxt ); /* plaintext result */
const void* crtxt, /* ciphertext + appended tag */
const size_t crtxtLen, /* length of ciphertext */
void* pntxt ); /* plaintext result */
#endif /* CCM */
/**----------------------------------------------------------------------------
@@ -325,21 +335,19 @@ Main functions for OCB-AES block ciphering
#if OCB
void AES_OCB_encrypt( const uint8_t* key, /* encryption key */
const uint8_t* nonce, /* nonce or IV (init. vector) */
const uint8_t* pntxt, /* plaintext input */
const size_t ptextLen, /* length of plaintext */
const uint8_t* aData, /* added authentication data */
const void* aData, /* added authentication data */
const size_t aDataLen, /* length of AAD (auth. data) */
uint8_t* crtxt, /* ciphertext result */
uint8_t* auTag ); /* message authentication tag */
const void* pntxt, /* plaintext input */
const size_t ptextLen, /* length of plaintext */
void* crtxt ); /* ciphertext + auth. tag */
char AES_OCB_decrypt( const uint8_t* key, /* decryption key */
const uint8_t* nonce, /* nonce or IV (init. vector) */
const uint8_t* crtxt, /* ciphertext + appended tag */
const size_t crtxtLen, /* length of ciphertext */
const uint8_t* aData, /* added authentication data */
const void* aData, /* added authentication data */
const size_t aDataLen, /* length of AAD (auth. data) */
const uint8_t tagLen, /* length of tag (=OCB_TAG_LEN) */
uint8_t* pntxt ); /* plaintext result */
const void* crtxt, /* ciphertext + appended tag */
const size_t crtxtLen, /* length of ciphertext */
void* pntxt ); /* plaintext result */
#endif /* OCB */
/**----------------------------------------------------------------------------
@@ -348,30 +356,27 @@ Main functions for EAX-AES mode; more info at the bottom of this document.
#if EAX
void AES_EAX_encrypt( const uint8_t* key, /* encryption key */
const uint8_t* nonce, /* arbitrary-size nonce array */
const uint8_t* pntxt, /* plaintext input */
const size_t ptextLen, /* length of plaintext */
#if EAXP
const size_t nonceLen, /* length of provided nonce */
uint8_t* crtxt ); /* ciphertext result + mac (4) */
#else
const uint8_t* aData, /* added authentication data */
const void* aData, /* added authentication data */
const size_t aDataLen, /* length of AAD (auth. data) */
uint8_t* crtxt, /* ciphertext result */
uint8_t auTag[16] ); /* message authentication tag */
#endif
const void* pntxt, /* plaintext input */
const size_t ptextLen, /* length of plaintext */
void* crtxt ); /* ciphertext+ appended tag/mac */
char AES_EAX_decrypt( const uint8_t* key, /* decryption key */
const uint8_t* nonce, /* arbitrary-size nonce array */
const uint8_t* crtxt, /* ciphertext + appended tag */
const size_t crtxtLen, /* length of ciphertext */
#if EAXP
const size_t nonceLen, /* length of provided nonce */
#else
const uint8_t* aData, /* added authentication data */
const void* aData, /* added authentication data */
const size_t aDataLen, /* length of AAD (auth. data) */
const uint8_t tagLen, /* length of tag (if any) */
#endif
uint8_t* pntxt ); /* plaintext result */
const void* crtxt, /* ciphertext+ appended tag/mac */
const size_t crtxtLen, /* length of ciphertext */
void* pntxt ); /* plaintext result */
#endif /* EAX */
/**----------------------------------------------------------------------------
@@ -380,21 +385,19 @@ Main functions for GCM-SIV-AES block ciphering
#if GCM_SIV
void GCM_SIV_encrypt( const uint8_t* key, /* encryption key */
const uint8_t* nonce, /* provided 96-bit nonce */
const uint8_t* pntxt, /* plaintext input */
const size_t ptextLen, /* length of plaintext */
const uint8_t* aData, /* added authentication data */
const void* aData, /* added authentication data */
const size_t aDataLen, /* length of AAD (auth. data) */
uint8_t* crtxt, /* ciphertext result */
uint8_t auTag[16] ); /* 16-bytes mandatory tag */
const void* pntxt, /* plaintext input */
const size_t ptextLen, /* length of plaintext */
void* crtxt ); /* ciphertext + auth. tag */
char GCM_SIV_decrypt( const uint8_t* key, /* decryption key */
const uint8_t* nonce, /* provided 96-bit nonce */
const uint8_t* crtxt, /* ciphertext + appended tag */
const size_t crtxtLen, /* length of ciphertext */
const uint8_t* aData, /* added authentication data */
const void* aData, /* added authentication data */
const size_t aDataLen, /* length of AAD (auth. data) */
const uint8_t tagLen, /* length of tag (must be 16) */
uint8_t* pntxt ); /* plaintext result */
const void* crtxt, /* ciphertext + appended tag */
const size_t crtxtLen, /* length of ciphertext */
void* pntxt ); /* plaintext result */
#endif /* GCM-SIV */
/**----------------------------------------------------------------------------
@@ -404,12 +407,12 @@ Main functions for AES key-wrapping
char AES_KEY_wrap( const uint8_t* kek, /* key encryption key */
const void* secret, /* the secret to be wrapped */
const size_t secretLen, /* length of plaintext secret */
uint8_t* wrapped ); /* key-wrapped output */
void* wrapped ); /* key-wrapped output */
char AES_KEY_unwrap( const uint8_t* kek, /* key encryption key */
const void* wrapped, /* key-wrapped secret */
const size_t wrapLen, /* length of wrapped secret */
uint8_t* secret ); /* the unwrapped key result */
void* secret ); /* the unwrapped key result */
#endif /* KWA */
/**----------------------------------------------------------------------------
@@ -461,27 +464,22 @@ void AES_CMAC( const uint8_t* key, /* encryption or cipher key */
#endif
/**----------------------------------------------------------------------------
The error codes and key length should be defined here for external references:
Define some error codes here
-----------------------------------------------------------------------------*/
#if AES___ != 256 && AES___ != 192
#define AES_KEY_SIZE 16
#else
#define AES_KEY_SIZE (AES___ / 8)
#endif
enum function_result_codes
{
M_ENCRYPTION_ERROR = 0x1E,
M_DECRYPTION_ERROR = 0x1D,
M_AUTHENTICATION_ERROR = 0x1A,
M_RESULT_SUCCESS = 0x00
M_DATALENGTH_ERROR = 0x1L,
M_RESULT_SUCCESS = 0
};
#endif /* header guard */
/******************************************************************************\
/*----------------------------------------------------------------------------*\
¦ Notes and remarks about the above-defined macros ¦
--------------------------------------------------------------------------------
------------------------------------------------------------------------------
* The main difference between the standard AES methods is in their key-expansion
process. So for example, AES-128-GCM and AES-256-GCM are pretty much similar
@@ -509,11 +507,11 @@ enum function_result_codes
a part of the I.V, which itself can either be a full block or a partial one.
In CBC, CFB and OFB modes, the provided IV must be a full block. In pure CTR
(CTR_NA) mode, the IV can either be a full block, or a 96 bit one —which is
also called nonce. In the latter case, counting begins at CTR_STARTVALUE.
also called nonce. In the latter case, counting begins at CTR_START_VALUE.
* In AEAD modes, the size of nonce and tag might be a parameter of the algorithm
such that changing them affect the results. The GCM and EAX modes support
arbitrary sizes for nonce. In CCM, the nonce length may vary from 8 to 13
* In AEAD modes, the size of nonce and tag are considered as constant parameters
and changing them might affect the results. The GCM and EAX modes support
arbitrary sizes for nonce. In CCM, the nonce length may vary from 7 to 13
bytes. Also the tag size is an EVEN number between 4..16. In OCB, the nonce
size is 1..15 and the tag is 0..16 bytes. Note that the "calculated" tag-
size is always 16 bytes which is then truncated to the desired values. So in
@@ -530,7 +528,7 @@ enum function_result_codes
* For the EAX mode of operation, the IEEE-1703 standard defines EAX' which is a
modified version that combines AAD and nonce. Also the tag size is fixed on
4 bytes. So EAX-prime functions don't need to take additional authentication
data and tag-size as separate parameters. It has been proven that EAX' has
data and its size as separate parameters. It has been proven that EAX' has
serious vulnerabilities and its usage is not recommended.
* In SIV mode, multiple separate units of authentication headers can be provided
@@ -556,7 +554,7 @@ enum function_result_codes
length of the input cipher/plain text is 'always' less than 4KB, you can
enable the SMALL_CIPHER macro to save a few bytes in the compiled code. This
assumption is likely to be valid for some embedded systems and small-scale
applications. Furthermore, enabling the DISCARD_SUBROUTINES macro may have a
applications. Furthermore, enabling the INLINE_SUBROUTINES macro may have a
positive effect on the speed while increasing the size of compiled code.
Nonetheless, it is also possible to get different results sometimes.

View File

@@ -2,7 +2,7 @@
==============================================================================
Name : micro_fpe.h
Author : polfosol
Version : 2.2.0.0
Version : 11
Copyright : copyright © 2022 - polfosol
Description : demonstrating some sample alphabets for the FPE mode of μAES ™
==============================================================================
@@ -11,159 +11,144 @@
#ifndef MICRO_FPE_H_
#define MICRO_FPE_H_
/******************************************************************************
* In what follows, a few sample alphabets and their corresponding macros are
* provided. Accordingly, it would be straightforward to define any alphabet.
/**
* If your desired alphabet contains non-ASCII characters, the CUSTOM_ALPHABET
* macro 'must be' set to a double-digit number, e.g. 21. The declaration of an
* alphabet needs to be followed by its number of characters (RADIX).
* macro 'must be' set to a double-digit number, e.g. 21.
*/
#define NON_ASCII_CHARACTER_SET (CUSTOM_ALPHABET >= 10)
#define ALPHABET_IS_NON_ASCII (CUSTOM_ALPHABET >= 10)
#if ALPHABET_IS_NON_ASCII
/**
* Note that C89/ANSI-C standard does not fully support such characters, and the
* code may lose its compliance in this case.
*/
#include <locale.h>
#include <wchar.h>
/******************************************************************************
#else
/**
* These strings frequently appear in ASCII-based alphabets.
*/
#define DECIMALS "0123456789"
#define DIGITS01 "01"
#define LLETTERS "abcdefghijklmnopqrstuvwxyz"
#define ULETTERS "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define HEXCHARS DECIMALS "ABCDEFabcdef"
#define DECIMALS DIGITS01"23456789"
#endif
/**
numbers
* In what follows, a few sample alphabets and their corresponding macros are
* provided. Accordingly, it would be straightforward to work with any kind of
* alphabets. The declaration of an alphabet must be followed by its number of
* characters (RADIX).
*/
#if CUSTOM_ALPHABET == 0
#if !CUSTOM_ALPHABET
#define ALPHABET DECIMALS
#define RADIX 10
#endif
/**
binary numbers
*/
#if CUSTOM_ALPHABET == 1
#define ALPHABET "01"
#define RADIX 2
#endif
/**
lowercase english words
*/
#if CUSTOM_ALPHABET == 2
#elif CUSTOM_ALPHABET == 1
#define ALPHABET LLETTERS
#define RADIX 26
#endif
/**
PLACEHOLDER: define your ASCII alphabet here
*/
#elif CUSTOM_ALPHABET == 2
#define ALPHABET "my Alphabet"
#define RADIX 11
/**
binary numbers
*/
#elif CUSTOM_ALPHABET == 3
#define ALPHABET DIGITS01
#define RADIX 2
/**
lowercase alphanumeric strings
*/
#if CUSTOM_ALPHABET == 3
#elif CUSTOM_ALPHABET == 4
#define ALPHABET DECIMALS LLETTERS
#define RADIX 36
#endif
/**
the English alphabet
*/
#if CUSTOM_ALPHABET == 4
#define ALPHABET ULETTERS LLETTERS
#define RADIX 52
#endif
/**
base-64 encoded strings (RFC-4648), with no padding character
*/
#if CUSTOM_ALPHABET == 5
#elif CUSTOM_ALPHABET == 5
#define ALPHABET ULETTERS LLETTERS DECIMALS "+/"
#define RADIX 64
#endif
/**
base-85 encoded strings (RFC-1924)
*/
#if CUSTOM_ALPHABET == 6
#elif CUSTOM_ALPHABET == 6
#define ALPHABET DECIMALS ULETTERS LLETTERS "!#$%&()*+-;<=>?@^_`{|}~"
#define RADIX 85
#endif
/**
a character set with length 26, used by some test vectors
*/
#if CUSTOM_ALPHABET == 7
#define ALPHABET DECIMALS "abcdefghijklmnop"
#define RADIX 26
#endif
/**
base-64 character set with DIFFERENT ORDERING, used by some test vectors
*/
#if CUSTOM_ALPHABET == 8
#elif CUSTOM_ALPHABET == 7
#define ALPHABET DECIMALS ULETTERS LLETTERS "+/"
#define RADIX 64
#endif
/**
a character set with length 26, used by some test vectors
*/
#elif CUSTOM_ALPHABET == 8
#define ALPHABET DECIMALS LLETTERS
#define RADIX 26
/**
all printable ascii characters
*/
#if CUSTOM_ALPHABET == 9
#elif CUSTOM_ALPHABET == 9
#define ALPHABET " !\"#$%&\'()*+,-./"DECIMALS":;<=>?@"ULETTERS"[\\]^_`"LLETTERS"{|}~"
#define RADIX 95
#endif
/******************************************************************************
* Here goes non-ASCII alphabets. Note that C89/ANSI-C standard does not fully
* support such characters, and the code may lose its compliance in this case.
*/
#if NON_ASCII_CHARACTER_SET
#include <locale.h>
#include <wchar.h>
#define string_t wchar_t* /* type of plain/cipher-text */
#else
#define string_t char*
#endif
/**
And here goes NON-ASCII alphabets. The string literal must have an L-prefix.
------------------------------------------------------------------------------
**
Greek alphabet (LTR)
*/
#if CUSTOM_ALPHABET == 10
#elif CUSTOM_ALPHABET == 10
#define ALPHABET L"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθικλμνξοπρσςτυφϕχψω"
#define RADIX 50
#endif
/**
Persian alphabet (RTL)
*/
#if CUSTOM_ALPHABET == 20
#elif CUSTOM_ALPHABET == 20
#define ALPHABET L"ءئؤآابپتثجچحخدذرزژسشصضطظعغفقکگلمنوهی"
#define RADIX 36
#endif
/******************************************************************************
* It is mandatory to determine these constants for the alphabet. You can either
* pre-calculate the logarithm value (with at least 15 significant digits) and
* set it as a constant, or leave its calculation to the standard math library.
* Other constants are directly related to the value of logarithm, and MAXLEN is
* needed only in the FF3 mode.
*
#define MINLEN (RADIX < 8 ? 40 / RADIX + (RADIX / 4) * (RADIX - 4) : \
(RADIX < 1000) + (RADIX < 100) - (RADIX == 10) + 2 + 31 / RADIX)
*
* The above lines illustrate that MINLEN can also be defined independently,
* using pure integer arithmetics.
/**
* You can either pre-calculate the value of logarithm (up to 14 decimal places
* to be safe) and set it as a constant, or use the standard math library.
*/
#include <math.h>
#ifdef MATH_ERRNO
#ifdef MATH_ERRNO /* then STDC version >= C99 */
#define LOGRDX log2( RADIX )
#else /* this means std-C <= C90 */
#else
#define LOGRDX (log( RADIX ) / log( 2 ))
#endif
#define MINLEN ((int) (19.931568 / LOGRDX + 1))
#define MINLEN (1 + (int) (19.931561 / LOGRDX))
#if FF_X == 3
#define MAXLEN (2 * (int) (96.000001 / LOGRDX))
#endif
/**
* MINLEN can also be defined independently, using pure integer arithmetics:
*
#define MINLEN (RADIX < 5 ? 40 / RADIX : \
32 / (1 + RADIX) + (RADIX < 100) + (RADIX < 1000) + 2)
*/
#endif /* header guard */

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -30,15 +30,13 @@
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
@@ -47,8 +45,6 @@
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -61,8 +57,6 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
@@ -75,9 +69,6 @@
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile Include="testvectors\aes_testvectors.c" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile Include="main.c" />
</ItemGroup>
@@ -88,6 +79,7 @@
<ClInclude Include="testvectors\aes_testvectors.h" />
<ClInclude Include="testvectors\aes_testvectors_CCM.h" />
<ClInclude Include="testvectors\aes_testvectors_CMAC.h" />
<ClInclude Include="testvectors\aes_testvectors_EAX.h" />
<ClInclude Include="testvectors\aes_testvectors_FPE.h" />
<ClInclude Include="testvectors\aes_testvectors_GCM.h" />
<ClInclude Include="testvectors\aes_testvectors_GCMSIV.h" />
@@ -95,7 +87,7 @@
<ClInclude Include="testvectors\aes_testvectors_POLY1305.h" />
<ClInclude Include="testvectors\aes_testvectors_XTS.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<ItemGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile Include="testvectors\aes_testvectors.c" />
</ItemGroup>
</Project>

64
testvectors/EAX_AES128.tv Normal file
View File

@@ -0,0 +1,64 @@
# EAX-AES-128 test vectors
# Taken from:
# Bellare, M., Rogaway, P., Wagner, D.A. (2004). The EAX Mode of Operation. Fast Software Encryption Workshop.
MSG:
KEY: 233952DEE4D5ED5F9B9C6D6FF80FF478
NONCE: 62EC67F9C3A4A407FCB2A8C49031A8B3
HEADER: 6BFB914FD07EAE6B
CIPHER: E037830E8389F27B025A2D6527E79D01
MSG: F7FB
KEY: 91945D3F4DCBEE0BF45EF52255F095A4
NONCE: BECAF043B0A23D843194BA972C66DEBD
HEADER: FA3BFD4806EB53FA
CIPHER: 19DD5C4C9331049D0BDAB0277408F67967E5
MSG: 1A47CB4933
KEY: 01F74AD64077F2E704C0F60ADA3DD523
NONCE: 70C3DB4F0D26368400A10ED05D2BFF5E
HEADER: 234A3463C1264AC6
CIPHER: D851D5BAE03A59F238A23E39199DC9266626C40F80
MSG: 481C9E39B1
KEY: D07CF6CBB7F313BDDE66B727AFD3C5E8
NONCE: 8408DFFF3C1A2B1292DC199E46B7D617
HEADER: 33CCE2EABFF5A79D
CIPHER: 632A9D131AD4C168A4225D8E1FF755939974A7BEDE
MSG: 40D0C07DA5E4
KEY: 35B6D0580005BBC12B0587124557D2C2
NONCE: FDB6B06676EEDC5C61D74276E1F8E816
HEADER: AEB96EAEBE2970E9
CIPHER: 071DFE16C675CB0677E536F73AFE6A14B74EE49844DD
MSG: 4DE3B35C3FC039245BD1FB7D
KEY: BD8E6E11475E60B268784C38C62FEB22
NONCE: 6EAC5C93072D8E8513F750935E46DA1B
HEADER: D4482D1CA78DCE0F
CIPHER: 835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F
MSG: 8B0A79306C9CE7ED99DAE4F87F8DD61636
KEY: 7C77D6E813BED5AC98BAA417477A2E7D
NONCE: 1A8C98DCD73D38393B2BF1569DEEFC19
HEADER: 65D2017990D62528
CIPHER: 02083E3979DA014812F59F11D52630DA30137327D10649B0AA6E1C181DB617D7F2
MSG: 1BDA122BCE8A8DBAF1877D962B8592DD2D56
KEY: 5FFF20CAFAB119CA2FC73549E20F5B0D
NONCE: DDE59B97D722156D4D9AFF2BC7559826
HEADER: 54B9F04E6A09189A
CIPHER: 2EC47B2C4954A489AFC7BA4897EDCDAE8CC33B60450599BD02C96382902AEF7F832A
MSG: 6CF36720872B8513F6EAB1A8A44438D5EF11
KEY: A4A4782BCFFD3EC5E7EF6D8C34A56123
NONCE: B781FCF2F75FA5A8DE97A9CA48E522EC
HEADER: 899A175897561D7E
CIPHER: 0DE18FD0FDD91E7AF19F1D8EE8733938B1E8E7F6D2231618102FDB7FE55FF1991700
MSG: CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7
KEY: 8395FCF1E95BEBD697BD010BC766AAC3
NONCE: 22E7ADD93CFC6393C57EC0B3C17D6B44
HEADER: 126735FCC320D25A
CIPHER: CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E

View File

@@ -42,6 +42,7 @@
<Unit filename="aes_testvectors.h" />
<Unit filename="aes_testvectors_CCM.h" />
<Unit filename="aes_testvectors_CMAC.h" />
<Unit filename="aes_testvectors_EAX.h" />
<Unit filename="aes_testvectors_FPE.h" />
<Unit filename="aes_testvectors_GCM.h" />
<Unit filename="aes_testvectors_GCMSIV.h" />

View File

@@ -2,7 +2,7 @@
==============================================================================
Name : aes_testvectors.c
Author : polfosol
Version : 1.1.0.0
Version : 1.2.0.0
Copyright : copyright © 2024 - polfosol
Description : check the test-vectors for enabled modes of µAES ™
==============================================================================
@@ -12,6 +12,7 @@
#include "aes_testvectors_CCM.h"
#include "aes_testvectors_XTS.h"
#include "aes_testvectors_FPE.h"
#include "aes_testvectors_EAX.h"
#include "aes_testvectors_OCB.h"
#include "aes_testvectors_GCMSIV.h"
#include "aes_testvectors_CMAC.h"
@@ -19,36 +20,33 @@
int main(void)
{
int ret = 0;
#ifdef CMAC_TEST_FILE
check_testvectors("CMAC", CMAC_TEST_FILE, &aes_cmac_test);
ret |= check_testvectors("CMAC", CMAC_TEST_FILE, &aes_cmac_test);
#endif
#ifdef POLY_TEST_FILE
check_testvectors("POLY1305", POLY_TEST_FILE, &aes_poly1305_test);
ret |= check_testvectors("POLY1305", POLY_TEST_FILE, &aes_poly1305_test);
#endif
#ifdef GCM_TEST_FILE
check_testvectors("GCM", GCM_TEST_FILE, &aes_gcm_test);
ret |= check_testvectors("GCM", GCM_TEST_FILE, &aes_gcm_test);
#endif
#ifdef CCM_TEST_FILE
check_testvectors("CCM", CCM_TEST_FILE, &aes_ccm_test);
ret |= check_testvectors("CCM", CCM_TEST_FILE, &aes_ccm_test);
#endif
#ifdef EAX_TEST_FILE
ret |= check_testvectors("EAX", EAX_TEST_FILE, &aes_eax_test);
#endif
#ifdef OCB_TEST_FILE
check_testvectors("OCB", OCB_TEST_FILE, &aes_ocb_test);
ret |= check_testvectors("OCB", OCB_TEST_FILE, &aes_ocb_test);
#endif
#ifdef GCMSIV_TEST_FILE
check_testvectors("GCM-SIV", GCMSIV_TEST_FILE, &aes_gcmsiv_test);
ret |= check_testvectors("GCM-SIV", GCMSIV_TEST_FILE, &aes_gcmsiv_test);
#endif
#ifdef XTS_TEST_FILE
check_testvectors("XTS", XTS_TEST_FILE, &aes_xts_test);
ret |= check_testvectors("XTS", XTS_TEST_FILE, &aes_xts_test);
#endif
#ifdef FPE_TEST_FILE
check_testvectors("FPE", FPE_TEST_FILE, &aes_fpe_test);
ret |= check_testvectors("FPE", FPE_TEST_FILE, &aes_fpe_test);
#endif
return 0;
return ret;
}

View File

@@ -2,7 +2,7 @@
==============================================================================
Name : aes_testvectors.h
Author : polfosol
Version : 1.1.0.0
Version : 1.2.0.0
Copyright : copyright © 2024 - polfosol
Description : methods and definitions for the test-functions of AES modes
==============================================================================
@@ -12,81 +12,152 @@
#define _TEST_AES_MODES_H_
#include <stdio.h>
#include <stdlib.h>
#include "../micro_aes.h"
#ifdef _CRT_SECURE_NO_WARNINGS
#define _LOOKUP_ "testvectors/"
#define VEC_PATH "testvectors/"
#else
#define _LOOKUP_
#define VEC_PATH
#endif
#if CMAC
#if AES___ == 256
#define CMAC_TEST_FILE _LOOKUP_ "CMACGenAES256.rsp"
#define CMAC_TEST_FILE VEC_PATH "CMACGenAES256.rsp"
#elif AES___ == 192
#define CMAC_TEST_FILE _LOOKUP_ "CMACGenAES192.rsp"
#define CMAC_TEST_FILE VEC_PATH "CMACGenAES192.rsp"
#else
#define CMAC_TEST_FILE _LOOKUP_ "CMACGenAES128.rsp"
#define CMAC_TEST_FILE VEC_PATH "CMACGenAES128.rsp"
#endif
#define CMAC_HEADLINES { "Key = ", "Msg = ", "Mac = " }
#endif
#if CCM
#if AES___ == 256
#define CCM_TEST_FILE _LOOKUP_ "ccmVNT256.rsp"
#define CCM_TEST_FILE VEC_PATH "VNT256.rsp"
#elif AES___ == 192
#define CCM_TEST_FILE _LOOKUP_ "ccmVNT192.rsp"
#define CCM_TEST_FILE VEC_PATH "VNT192.rsp"
#else
#define CCM_TEST_FILE _LOOKUP_ "ccmVNT128.rsp"
#define CCM_TEST_FILE VEC_PATH "VNT128.rsp"
#endif
#define CCM_HEADLINES { "Key = ", "Nonce = ", "Adata = ", "Payload = ", "CT = " }
#endif
#if GCM
#if AES___ == 256
#define GCM_TEST_FILE _LOOKUP_ "gcmEncryptExtIV256.rsp"
#define GCM_TEST_FILE VEC_PATH "GcmEncryptExtIV256.rsp"
#elif AES___ == 192
#define GCM_TEST_FILE _LOOKUP_ "gcmEncryptExtIV192.rsp"
#define GCM_TEST_FILE VEC_PATH "GcmEncryptExtIV192.rsp"
#else
#define GCM_TEST_FILE _LOOKUP_ "gcmEncryptExtIV128.rsp"
#define GCM_TEST_FILE VEC_PATH "GcmEncryptExtIV128.rsp"
#endif
#define GCM_HEADLINES { "Key = ", "IV = ", "AAD = ", "PT = ", "CT = ", "Tag = " }
#endif
#if XTS
#if AES___ == 256
#define XTS_TEST_FILE _LOOKUP_ "XTSGenAES256.rsp"
#else
#define XTS_TEST_FILE _LOOKUP_ "XTSGenAES128.rsp"
#define XTS_TEST_FILE VEC_PATH "XTSGenAES256.rsp"
#elif AES___ != 192
#define XTS_TEST_FILE VEC_PATH "XTSGenAES128.rsp"
#endif
#define XTS_HEADLINES { "Key = ", "i = ", "PT = ", "CT = ", "DataUnitLen = " }
#endif
#if POLY1305
#define POLY_TEST_FILE VEC_PATH "Poly1305AES128.tv"
#define POLY_HEADLINES { "Keys = ", "Nonce = ", "Msg = ", "PolyMac = " }
#endif
#if EAX
#define EAX_TEST_FILE VEC_PATH "EAX_AES128.tv"
#define EAX_HEADLINES { "MSG: ", "KEY: ", "NONCE: ", "HEADER: ", "CIPHER: " }
#endif
#if GCM_SIV
#define GCMSIV_TEST_FILE VEC_PATH "SIV_GCM_ACVP.tv"
#define GCMSIV_HEADLINES { "key = ", "iv = ", "aad = ", "pt = ", "ct = " }
#endif
#if FPE
#define FPE_TEST_FILE _LOOKUP_ "FPE_FF1&FF3&FF3-1.tv"
#define FPE_TEST_FILE VEC_PATH "FPE_FF1&FF3&FF3-1.tv"
#define FPE_HEADLINES { "Method = ", "Alphabet = ", "Key = ", "Tweak = ", \
"PT = ", "CT = " }
#define FPE_ALPHABETS { "0123456789", "01", "abcdefghijklmnopqrstuvwxyz", \
"0123456789abcdefghijklmnopqrstuvwxyz", "******", \
"*******", "*****", "0123456789abcdefghijklmnop", \
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/" }
#define FPE_ALPHABETS { DECIMALS, LLETTERS, "PLACEHOLDER: your alphabet", \
DIGITS01, DECIMALS LLETTERS, ULETTERS LLETTERS DECIMALS "+/", \
DECIMALS ULETTERS LLETTERS "!#$%&()*+-;<=>?@^_`{|}~", DECIMALS \
ULETTERS LLETTERS "+/", DECIMALS "abcdefghijklmnop", " !\"#$%&" \
"\'()*+,-./" DECIMALS ":;<=>?@" ULETTERS"[\\]^_`" LLETTERS"{|}~" }
#endif
#if OCB
#define OCB_TEST_FILE _LOOKUP_ "OCB_AES128.tv"
#define OCB_TEST_FILE VEC_PATH "OCB_AES128.tv"
#define OCB_HEADLINES { "Key = ", "IV = ", "AAD = ", "Plaintext = ", \
"Ciphertext = ", "Tag = ", "Result = " }
#endif
#if GCM_SIV
#define GCMSIV_TEST_FILE _LOOKUP_ "SIV_GCM_ACVP.tv"
#define GCMSIV_HEADLINES { "key = ", "iv = ", "aad = ", "pt = ", "ct = " }
#endif
#define LINES_MAX_LEN 0x20040L /* maximum length of a line among all files. */
#if POLY1305
#define POLY_TEST_FILE _LOOKUP_ "Poly1305AES128.tv"
#define POLY_HEADLINES { "Keys = ", "Nonce = ", "Msg = ", "PolyMac = " }
#endif
/** function pointer as a template for all the test functions. its arguments are
* an array of pre-determined files and the number of test cases/failed ones. */
typedef void (*ftest_t)(FILE**, unsigned*);
static int check_testvectors(const char* mode, const char* path, ftest_t test)
{
char i, log[2][22], error = -1;
FILE* files[3]; /* test vectors file, success log, errors log */
unsigned count[3] = { 0 }; /* total tests, encrypt fails, decrypt fails. */
printf("\nVerifying vectors: AES%d-%s\n", AES_KEYLENGTH * 8, mode);
files[0] = fopen(path, "r");
files[1] = fopen(strcat(strcpy(log[0], mode), "success.log"), "w");
files[2] = fopen(strcat(strcpy(log[1], mode), "failure.log"), "w");
if (files[0] && files[1] && files[2])
{
test(files, count);
error = count[1] || (count[2] && ~count[2]);
}
for (i = 0; i < 3; i++) /* close and delete unnecessary logs. */
{
if (files[i] && -fclose(files[i]) >= error)
{
error += i ? remove(log[i - 1]) : error;
}
}
switch (2 * !error + !*count)
{
case 0:
printf("Nmber of tests: %d, there were some errors.\n", count[0]);
if (count[2] == ~0U) /* MAC test, no encryption/decryption */
{
printf("Failed cases: %d, see the log files.\n", count[1]);
}
else
{
printf("Encryption failures: %d, decryption failures: %d\n"
"See the log files for more info.\n", count[1], count[2]);
}
break;
case 1:
printf("Error: Test has failed.\n");
if (error == -1)
{
printf("File not found: %s\n", path);
}
else
{
printf("Cannot save log files...\n");
}
break;
case 2:
printf("Nmber of tests: %3d, All Passed!\n", count[0]);
break;
case 3:
printf("No valid cases found in %s\n", path);
break;
}
return error;
}
/** convert hex-string to byte array; e.g. "7142075A340d" results in qB\aZ4\r */
static void str2bytes(const char* hex, uint8_t* bytes)
@@ -102,90 +173,14 @@ static void str2bytes(const char* hex, uint8_t* bytes)
/** convert byte array to hex-string; e.g. +\n50\tK results in "2b0a3530094b" */
static void bytes2str(const uint8_t* bytes, char* str, const size_t len)
#define UPPERCASE_HEXSTRING 0
{
const char offset = 0x27; /* offset must be 7 for UPPERCASE */
size_t i = len + len, shr = 0;
for (str[i] = 0; i--; shr ^= 4)
{
str[i] = bytes[i / 2] >> shr & 0xF | '0';
if (str[i] > '9') str[i] += offset;
str[i] = bytes[i / 2] >> shr & 0xF;
str[i] += str[i] < 10 ? '0' : (UPPERCASE_HEXSTRING ? '7' : 'W');
}
}
/** function pointer as a template for all the test functions. its arguments are
* an array of pre-determined files and the number of test cases/failed ones. */
typedef void (*ftest_t)(FILE**, unsigned*);
static int check_testvectors(const char* mode, const char* path, ftest_t test)
{
int error = 0, i;
char p_log[20], e_log[20];
FILE* files[3]; /* test vectors file, errors log, success log */
unsigned count[3]; /* total tests, encrypt fails, decrypt fails. */
printf("\nVerifying vectors: AES%d-%s\n", AES_KEY_SIZE * 8, mode);
strcpy(p_log, mode);
strcpy(e_log, mode);
files[0] = fopen(path, "r");
files[1] = fopen(strcat(p_log, "passed.log"), "w");
files[2] = fopen(strcat(e_log, "failed.log"), "w");
if (!files[0])
{
printf("Error: file not found: %s\n", path);
error |= 1;
}
if (!files[1] || !files[2])
{
printf("Error: cannot save log files...\n");
error |= 1;
}
if (error)
{
for (i = 0; i < 3; ++i)
{
if (files[i])
{
fclose(files[i]);
if (i) remove(i == 1 ? p_log : e_log);
}
}
printf("Test has failed.\n");
return error;
}
memset(count, 0, sizeof count);
test(files, count);
for (i = 0; i < 3; i++)
{
fclose(files[i]);
}
error = count[1] + (~count[2] ? count[2] : 0);
if (error)
{
printf("Nmber of tests: %d, there were some errors:\n", count[0]);
if (count[2] == ~0U) /* MAC test, no encryption/decryption */
{
printf("Failed cases: %d, see the log files.\n", count[1]);
}
else
{
printf("Encryption failures: %d, decryption failures: %d\n"
"See the log files for more info.\n", count[1], count[2]);
}
return error;
}
else
{
if (count[0] == 0) printf("There was no test cases.\n");
else
{
printf("Nmber of tests: %4d, All Passed!\n", count[0]);
}
remove(p_log);
remove(e_log);
}
return 0;
}
#endif /* header guard */

View File

@@ -2,39 +2,38 @@
==============================================================================
Name : aes_testvectors_CCM.h
Author : polfosol
Version : 1.1.0.0
Version : 1.2.0.0
Copyright : copyright © 2024 - polfosol
Description : checking the test vectors for AES-CCM
==============================================================================
*/
#ifndef _TESTING_CCM_H_
#include "aes_testvectors.h"
#if defined(_TESTING_CCM_H_) ^ defined(CCM_TEST_FILE)
#define _TESTING_CCM_H_
#include "aes_testvectors.h"
#ifdef CCM_TEST_FILE
static int verifyccm(uint8_t* key, uint8_t* i, uint8_t* p, uint8_t* a, uint8_t* c,
int verifyccm(uint8_t* key, uint8_t* i, uint8_t* p, uint8_t* a, uint8_t* c,
size_t np, size_t na, char* r)
{
char sk[2 * AES_KEY_SIZE + 1], si[33], sp[80], sc[96], sa[80], msg[30];
char sk[2 * AES_KEYLENGTH + 1], si[30], sp[80], sc[96], sa[80], msg[30];
uint8_t tmp[64], v = 0;
strcpy(msg, "passed the test");
AES_CCM_encrypt(key, i, p, np, a, na, tmp, tmp + np);
AES_CCM_encrypt(key, i, a, na, p, np, tmp);
if (memcmp(c, tmp, np + CCM_TAG_LEN))
{
strcpy(msg, "encrypt failure");
v = 1;
}
memset(tmp, 0xcc, sizeof tmp);
*sk = AES_CCM_decrypt(key, i, c, np, a, na, CCM_TAG_LEN, tmp);
if (*sk || memcmp(p, tmp, np))
*r = AES_CCM_decrypt(key, i, a, na, c, np, tmp);
if (*r || memcmp(p, tmp, np))
{
sprintf(msg, "%sdecrypt failure", v ? "encrypt & " : "");
strcat(strcpy(msg, v ? "encrypt & " : ""), "decrypt failure");
v |= 2;
}
bytes2str(key, sk, AES_KEY_SIZE);
bytes2str(key, sk, AES_KEYLENGTH);
bytes2str(i, si, CCM_NONCE_LEN);
bytes2str(p, sp, np);
bytes2str(a, sa, na);
@@ -43,34 +42,29 @@ static int verifyccm(uint8_t* key, uint8_t* i, uint8_t* p, uint8_t* a, uint8_t*
return v;
}
static void aes_ccm_test(FILE** files, unsigned* count)
void aes_ccm_test(FILE** files, unsigned* count)
{
const char *linehdr[] = CCM_HEADLINES;
const char* head[] = CCM_HEADLINES;
char buffer[0x800], *value = NULL;
size_t s[5] = { 0 };
uint8_t j, n = 0, key[AES_KEY_SIZE], iv[16], p[64], c[80], a[64];
uint8_t h, e = 0, key[32], iv[15], p[64], c[80], a[64];
while (fgets(buffer, sizeof buffer, *files) != NULL)
{
buffer[ strcspn(buffer, "\n") ] = 0;
if (strlen(buffer) < 4) continue;
for (j = 0; j < 5; j++)
{
if (strncmp(buffer, linehdr[j], strlen(linehdr[j])) == 0)
for (h = strlen(buffer) < 4 ? 5 : 0; h < 5; ++h)
{
if (strncmp(buffer, head[h], strlen(head[h])) != 0) continue;
value = strrchr(buffer, ' ') + 1;
s[j] = strlen(value) / 2;
n += j > 2;
break;
}
}
switch (j)
s[h] = strlen(value) / 2 - CCM_TAG_LEN * (h == 4);
switch (h)
{
case 0:
if (s[0] == AES_KEY_SIZE) str2bytes(value, key);
str2bytes(value, key);
break;
case 1:
if (s[1] == CCM_NONCE_LEN) str2bytes(value, iv);
str2bytes(value, iv);
break;
case 2:
str2bytes(value, a);
@@ -79,24 +73,24 @@ static void aes_ccm_test(FILE** files, unsigned* count)
str2bytes(value, p);
break;
case 4:
s[4] -= CCM_TAG_LEN;
str2bytes(value, c);
break;
}
if (n == 2)
{
if (s[0] == AES_KEY_SIZE && s[1] == CCM_NONCE_LEN && s[3] == s[4])
{
n = verifyccm(key, iv, p, a, c, s[3], s[2], buffer);
fprintf(files[2 - !n], "%s\n", buffer); /* save the log */
++count[0];
if (n & 1) ++count[1];
if (n & 2) ++count[2];
e += (h == 3 || h == 4);
}
n = 0;
if (e == 2)
{
if (AES_KEYLENGTH == *s && CCM_NONCE_LEN == s[1] && s[3] == s[4])
{
e = verifyccm(key, iv, p, a, c, s[3], s[2], buffer);
fprintf(files[2 - !e], "%s\n", buffer); /* save the log */
++count[0];
if (e & 1) ++count[1];
if (e & 2) ++count[2];
}
e = 0;
}
}
}
#endif
#endif /* header guard */

View File

@@ -2,83 +2,86 @@
==============================================================================
Name : aes_testvectors_CMAC.h
Author : polfosol
Version : 1.1.0.0
Version : 1.2.0.0
Copyright : copyright © 2024 - polfosol
Description : checking the test vectors for AES-CMAC
==============================================================================
*/
#ifndef _TESTING_CMAC_H_
#include "aes_testvectors.h"
#if defined(_TESTING_CMAC_H_) ^ defined(CMAC_TEST_FILE)
#define _TESTING_CMAC_H_
#include "aes_testvectors.h"
#ifdef CMAC_TEST_FILE
static int verifycmac(uint8_t* key, uint8_t* d, uint8_t* m,
int verifycmac(uint8_t* key, uint8_t* d, uint8_t* m,
size_t nd, size_t nm, char* r)
{
char sk[2 * AES_KEY_SIZE + 1], smac[33], msg[30];
char sk[2 * AES_KEYLENGTH + 1], smac[33], msg[30];
uint8_t tmp[16], v = 0;
strcpy(msg, "passed the test");
AES_CMAC(key, d, nd, tmp);
if ((v = memcmp(m, tmp, nm)) != 0) strcpy(msg, "failed");
bytes2str(key, sk, AES_KEY_SIZE);
bytes2str(key, sk, AES_KEYLENGTH);
bytes2str(m, smac, nm);
sprintf(r, "%s\nK: %s\nmac: %s\n", msg, sk, smac);
return v;
}
static void aes_cmac_test(FILE** files, unsigned* count)
void aes_cmac_test(FILE** files, unsigned* count)
{
const char *linehdr[] = CMAC_HEADLINES;
char buffer[0x20100], *value = NULL;
const char* head[] = CMAC_HEADLINES;
size_t s[3] = { 0 };
uint8_t j, n = 0, key[AES_KEY_SIZE], d[0x10100], m[16];
uint8_t h, *d, e = 0, key[AES_KEYLENGTH], m[16];
char *value = NULL, *buffer;
count[2] = ~0U;
while (fgets(buffer, sizeof buffer, *files) != NULL)
if ((buffer = malloc(LINES_MAX_LEN / 2 * 3)) == NULL)
{
printf("Memory allocation failed.\n");
return;
}
while (fgets(buffer, LINES_MAX_LEN, *files) != NULL)
{
buffer[ strcspn(buffer, "\n") ] = 0;
if (strlen(buffer) < 4) continue;
for (j = 0; j < 3; j++)
for (h = strlen(buffer) < 4 ? 3 : 0; h < 3; ++h)
{
if (strncmp(buffer, linehdr[j], strlen(linehdr[j])) == 0)
if (strncmp(buffer, head[h], strlen(head[h])) == 0)
{
value = strrchr(buffer, ' ') + 1;
s[j] = strlen(value) / 2;
n += j > 0;
d = (uint8_t*) &buffer[LINES_MAX_LEN];
s[h] = strlen(value) / 2;
e += (h == 1 || h == 2);
break;
}
}
switch (j)
switch (h)
{
case 0:
if (s[0] == AES_KEY_SIZE) str2bytes(value, key);
if (s[0] == sizeof key) str2bytes(value, key);
break;
case 1:
str2bytes(value, d);
s[1] -= (s[1] == 1 && d[0] == 0); /* null message */
s[1] -= (s[1] == !d[0]); /* null message */
break;
case 2:
str2bytes(value, m);
break;
}
if (n == 2)
if (e == 2)
{
if (s[0] == AES_KEY_SIZE)
if (s[0] == sizeof key)
{
n = verifycmac(key, d, m, s[1], s[2], buffer);
fprintf(files[2 - !n], "%s\n", buffer); /* save the log */
e = verifycmac(key, d, m, s[1], s[2], buffer);
fprintf(files[2 - !e], "%s\n", buffer); /* save the log */
++count[0];
if (n) ++count[1];
count[1] += e != 0;
}
n = 0;
e = 0;
}
}
free(buffer);
}
#endif
#endif /* header guard */

View File

@@ -0,0 +1,96 @@
/*
==============================================================================
Name : aes_testvectors_EAX.h
Author : polfosol
Version : 1.0.0.0
Copyright : copyright © 2024 - polfosol
Description : checking the test vectors for AES-EAX
==============================================================================
*/
#include "aes_testvectors.h"
#if defined(_TESTING_EAX_H_) ^ defined(EAX_TEST_FILE)
#define _TESTING_EAX_H_
int verifyeax(uint8_t* key, uint8_t* i, uint8_t* p, uint8_t* a, uint8_t* c,
size_t np, size_t na, char* r)
{
char sk[2 * AES_KEYLENGTH + 1], si[33], sp[80], sc[96], sa[80], msg[30];
uint8_t tmp[64], v = 0;
strcpy(msg, "passed the test");
AES_EAX_encrypt(key, i, a, na, p, np, tmp);
if (memcmp(c, tmp, np + EAX_TAG_LEN))
{
strcpy(msg, "encrypt failure");
v = 1;
}
memset(tmp, 0xcc, sizeof tmp);
*r = AES_EAX_decrypt(key, i, a, na, c, np, tmp);
if (*r || memcmp(p, tmp, np))
{
strcat(strcpy(msg, v ? "encrypt & " : ""), "decrypt failure");
v |= 2;
}
bytes2str(key, sk, AES_KEYLENGTH);
bytes2str(i, si, EAX_NONCE_LEN);
bytes2str(p, sp, np);
bytes2str(a, sa, na);
bytes2str(c, sc, np + EAX_TAG_LEN);
sprintf(r, "%s\nK: %s\ni: %s\nP: %s\nA: %s\nC: %s", msg, sk, si, sp, sa, sc);
return v;
}
void aes_eax_test(FILE** files, unsigned* count)
{
const char* head[] = EAX_HEADLINES;
char buffer[0x400], *value = NULL;
size_t s[5] = { 0 };
uint8_t h, e = 0, key[32], iv[EAX_NONCE_LEN], p[32], c[48], a[32];
while (fgets(buffer, sizeof buffer, *files) != NULL)
{
buffer[ strcspn(buffer, "\n") ] = 0;
for (h = strlen(buffer) < 4 ? 5 : 0; h < 5; ++h)
{
if (strncmp(buffer, head[h], strlen(head[h])) != 0) continue;
value = strrchr(buffer, ' ') + 1;
s[h] = strlen(value) / 2 - EAX_TAG_LEN * (h == 4);
switch (h)
{
case 0:
str2bytes(value, p);
break;
case 1:
str2bytes(value, key);
break;
case 2:
if (s[2] == sizeof iv) str2bytes(value, iv);
break;
case 3:
str2bytes(value, a);
break;
case 4:
str2bytes(value, c);
break;
}
e += (h == 3 || h == 4);
}
if (e == 2)
{
if (s[1] == AES_KEYLENGTH && s[2] == EAX_NONCE_LEN && s[4] == *s)
{
e = verifyeax(key, iv, p, a, c, s[0], s[3], buffer);
fprintf(files[2 - !e], "%s\n", buffer); /* save the log */
++count[0];
if (e & 1) ++count[1];
if (e & 2) ++count[2];
}
e = 0;
}
}
}
#endif /* header guard */

View File

@@ -2,119 +2,108 @@
==============================================================================
Name : aes_testvectors_FPE.h
Author : polfosol
Version : 1.1.0.0
Version : 1.2.0.0
Copyright : copyright © 2024 - polfosol
Description : checking the test vectors for AES-FPE
==============================================================================
*/
#ifndef _TESTING_FPE_H_
#define _TESTING_FPE_H_
#include "aes_testvectors.h"
#ifdef FPE_TEST_FILE
static int verifyfpe(uint8_t* key, uint8_t* twk, char* a, char* p, char* c,
#if defined(_TESTING_FPE_H_) ^ defined(FPE_TEST_FILE)
#define _TESTING_FPE_H_
#include "../micro_fpe.h"
int verifyfpe(uint8_t* key, uint8_t* twk, const char* a, char* p, char* c,
size_t np, size_t nt, char* r)
{
char sk[2 * AES_KEY_SIZE + 1], st[65], msg[30], tmp[0x800], v = 0;
strcpy(msg, "passed the test");
#if FF_X == 3
AES_FPE_encrypt(key, twk, p, np, tmp);
#define TWK_ARGS twk
#else
AES_FPE_encrypt(key, twk, nt, p, np, tmp);
#define TWK_ARGS twk, nt
#endif
char sk[2 * AES_KEYLENGTH + 1], st[65], msg[30], tmp[0x800], v = 0;
strcpy(msg, "passed the test");
AES_FPE_encrypt(key, TWK_ARGS, p, np, tmp);
if (memcmp(c, tmp, np))
{
strcpy(msg, "encrypt failure");
v = 1;
}
memset(tmp, 0xcc, sizeof tmp);
#if FF_X == 3
*sk = AES_FPE_decrypt(key, twk, c, np, tmp);
#else
*sk = AES_FPE_decrypt(key, twk, nt, c, np, tmp);
#endif
if (*sk || memcmp(p, tmp, np))
*r = AES_FPE_decrypt(key, TWK_ARGS, c, np, tmp);
if (*r || memcmp(p, tmp, np))
{
sprintf(msg, "%sdecrypt failure", v ? "encrypt & " : "");
strcat(strcpy(msg, v ? "encrypt & " : ""), "decrypt failure");
v |= 2;
}
bytes2str(key, sk, AES_KEY_SIZE);
bytes2str(key, sk, AES_KEYLENGTH);
bytes2str(twk, st, nt);
sprintf(r, "%s\nA: %s\nK: %s\nT: %s\nP: %s\nC: %s", msg, a, sk, st, p, c);
return v;
}
static void aes_fpe_test(FILE** files, unsigned* count)
void aes_fpe_test(FILE** files, unsigned* count)
{
const char *linehdr[] = FPE_HEADLINES, *alphabets[] = FPE_ALPHABETS;
char buffer[0x1000], alpha[90], p[0x800], c[0x800], m[6], a = 0, *value = NULL;
size_t s[3] = { 0 };
uint8_t j, key[2 * AES_KEY_SIZE], twk[32], n = 0;
const char *head[] = FPE_HEADLINES, *alphabets[] = FPE_ALPHABETS, *a;
char buffer[0x1000], p[0x800], c[0x800], *value = NULL;
size_t s[6] = { 0 };
uint8_t h, key[32], twk[32], e = 0;
while (fgets(buffer, sizeof buffer, *files) != NULL)
{
buffer[ strcspn(buffer, "\n") ] = 0;
if (strlen(buffer) < 4) continue;
for (j = 0; j < 6; j++)
for (h = strlen(buffer) < 4 ? 6 : 0; h < 6; ++h)
{
if (strncmp(buffer, linehdr[j], strlen(linehdr[j])) == 0)
if (strncmp(buffer, head[h], strlen(head[h])) == 0)
{
value = strrchr(buffer, ' ') + 1;
n += j > 2;
s[h] = h ? strlen(value) : value[2] != '3'; /* is it FF1 */
e += (h == 3 || h == 4 || h == 5);
break;
}
}
switch (j)
switch (h)
{
case 0:
strcpy(m, value);
break;
case 1:
for (j = 0; j < 9; j++)
{
if ((a = strlen(alphabets[j])) != strlen(value)) continue;
if (strncmp(value, alphabets[j], a) == 0) break;
}
strcpy(alpha, value), a = j;
do
a = alphabets[h - 1];
while ((strlen(a) != s[1] || memcmp(a, value, s[1])) && h++ < 10);
s[1] = h - 1;
break;
case 2:
s[0] = strlen(value) / 2;
s[2] /= 2;
str2bytes(value, key);
break;
case 3:
s[1] = strlen(value) / 2;
s[3] /= 2;
str2bytes(value, twk);
break;
case 4:
s[2] = strlen(value);
strcpy(p, value);
break;
case 5:
strcpy(c, value);
break;
}
if (n == 3)
if (e == 3)
{
n = (FF_X == 3) ^ (m[2] != '3');
#if FF3_TWEAK_LEN == 8
n &= s[1] == 8; /* old FF3 with 8-byte tweak */
#else
n &= FF_X != 3 || s[1] != 8 || !twk[7]; /* FF3-1 */
#if FF_X == 3
s[0] = !*s && (s[3] == FF3_TWEAK_LEN || !(twk[3] + twk[7]));
#endif
if (n && a == CUSTOM_ALPHABET && s[0] == AES_KEY_SIZE)
if (s[0] && s[1] == CUSTOM_ALPHABET && s[2] == AES_KEYLENGTH)
{
n = verifyfpe(key, twk, alpha, p, c, s[2], s[1], buffer);
fprintf(files[2 - !n], "%s\n\n", buffer); /* save the log */
e = verifyfpe(key, twk, a, p, c, s[4], s[3], buffer);
fprintf(files[2 - !e], "%s\n\n", buffer); /* save the log */
++count[0];
if (n & 1) ++count[1];
if (n & 2) ++count[2];
if (e & 1) ++count[1];
if (e & 2) ++count[2];
}
n = 0;
e = 0;
}
}
}
#endif
#endif /* header guard */

View File

@@ -2,78 +2,69 @@
==============================================================================
Name : aes_testvectors_GCM.h
Author : polfosol
Version : 1.1.0.0
Version : 1.2.0.0
Copyright : copyright © 2024 - polfosol
Description : checking the test vectors for AES-GCM
==============================================================================
*/
#ifndef _TESTING_GCM_H_
#include "aes_testvectors.h"
#if defined(_TESTING_GCM_H_) ^ defined(GCM_TEST_FILE)
#define _TESTING_GCM_H_
#include "aes_testvectors.h"
#ifdef GCM_TEST_FILE
static int verifygcm(uint8_t* key, uint8_t* i, uint8_t* p, uint8_t* a, uint8_t* c,
size_t np, size_t na, uint8_t nt, char* r)
int verifygcm(uint8_t* key, uint8_t* i, uint8_t* p, uint8_t* a, uint8_t* c,
size_t np, size_t na, char* r)
{
char sk[65], si[2 * GCM_NONCE_LEN + 1], sp[0x100], sc[0x100], sa[0x100], msg[30];
uint8_t tmp[0x80], v = 0;
strcpy(msg, "passed the test");
AES_GCM_encrypt(key, i, p, np, a, na, tmp, tmp + np);
if (memcmp(c, tmp, np + nt))
AES_GCM_encrypt(key, i, a, na, p, np, tmp);
if (memcmp(c, tmp, np + GCM_TAG_LEN))
{
strcpy(msg, "encrypt failure");
v = 1;
}
memset(tmp, 0xcc, sizeof tmp);
*sk = AES_GCM_decrypt(key, i, c, np, a, na, nt, tmp);
if (*sk || memcmp(p, tmp, np))
*r = AES_GCM_decrypt(key, i, a, na, c, np, tmp);
if (*r || memcmp(p, tmp, np))
{
sprintf(msg, "%sdecrypt failure", v ? "encrypt & " : "");
strcat(strcpy(msg, v ? "encrypt & " : ""), "decrypt failure");
v |= 2;
}
bytes2str(key, sk, AES_KEY_SIZE);
bytes2str(key, sk, AES_KEYLENGTH);
bytes2str(i, si, GCM_NONCE_LEN);
bytes2str(p, sp, np);
bytes2str(a, sa, na);
bytes2str(c, sc, np + nt);
bytes2str(c, sc, np + GCM_TAG_LEN);
sprintf(r, "%s\nK: %s\ni: %s\nP: %s\nA: %s\nC: %s", msg, sk, si, sp, sa, sc);
return v;
}
static void aes_gcm_test(FILE** files, unsigned* count)
void aes_gcm_test(FILE** files, unsigned* count)
{
const char *linehdr[] = GCM_HEADLINES;
char buffer[0x800], *value = NULL, *line = NULL;
const char* head[] = GCM_HEADLINES;
char buffer[0x800], *value = NULL;
size_t s[6] = { 0 };
uint8_t key[AES_KEY_SIZE], tmp[AES_KEY_SIZE], iv[GCM_NONCE_LEN];
uint8_t j, p[96], c[112], a[96], t[16], r = 1;
uint8_t h, e = 0, key[32], iv[GCM_NONCE_LEN], p[96], c[112], a[96];
do
{
if ((line = fgets(buffer, sizeof buffer, *files)) != NULL)
while (fgets(buffer, sizeof buffer, *files) != NULL)
{
buffer[ strcspn(buffer, "\n") ] = 0;
if (strlen(buffer) < 4) continue;
}
for (j = 0; j < 6; j++)
{
if (strncmp(buffer, linehdr[j], strlen(linehdr[j])) == 0)
for (h = strlen(buffer) < 4 ? 6 : 0; h < 6; ++h)
{
if (strncmp(buffer, head[h], strlen(head[h])) != 0) continue;
value = strrchr(buffer, ' ') + 1;
s[j] = strlen(value) / 2;
break;
}
}
switch (j)
s[h] = strlen(value) / 2;
switch (h)
{
case 0:
if (s[0] == AES_KEY_SIZE) str2bytes(value, tmp);
str2bytes(value, key);
break;
case 1:
if (s[1] == GCM_NONCE_LEN) str2bytes(value, iv);
if (s[1] == sizeof iv) str2bytes(value, iv);
break;
case 2:
str2bytes(value, a);
@@ -85,25 +76,24 @@ static void aes_gcm_test(FILE** files, unsigned* count)
str2bytes(value, c);
break;
case 5:
str2bytes(value, t);
str2bytes(value, c + s[4]);
break;
}
if (j == 0 || line == NULL)
e += (h == 3 || h == 4 || h == 5);
}
if (e == 3)
{
if (!r && s[1] == GCM_NONCE_LEN && s[0] == AES_KEY_SIZE)
if (AES_KEYLENGTH == *s && GCM_NONCE_LEN == s[1] && s[5] >= GCM_TAG_LEN)
{
memcpy(c + s[3], t, s[5]); /* put the tag at the end */
r = verifygcm(key, iv, p, a, c, s[3], s[2], s[5], buffer);
fprintf(files[2 - !r], "%s\n", buffer); /* save the log */
e = verifygcm(key, iv, p, a, c, s[3], s[2], buffer);
fprintf(files[2 - !e], "%s\n", buffer); /* save the log */
++count[0];
if (r & 1) ++count[1];
if (r & 2) ++count[2];
if (e & 1) ++count[1];
if (e & 2) ++count[2];
}
e = 0;
}
memcpy(key, tmp, sizeof key);
r = 0;
}
} while (line != NULL);
}
#endif
#endif /* header guard */

View File

@@ -2,75 +2,69 @@
==============================================================================
Name : aes_testvectors_GCMSIV.h
Author : polfosol
Version : 1.1.0.0
Version : 1.2.0.0
Copyright : copyright © 2024 - polfosol
Description : checking the test vectors for AES-GCM-SIV
==============================================================================
*/
#ifndef _TESTING_GCMSIV_H_
#include "aes_testvectors.h"
#if defined(_TESTING_GCMSIV_H_) ^ defined(GCMSIV_TEST_FILE)
#define _TESTING_GCMSIV_H_
#include "aes_testvectors.h"
#ifdef GCMSIV_TEST_FILE
static int verifygcmsiv(uint8_t* key, uint8_t* i, uint8_t* p, uint8_t* a, uint8_t* c,
int verifygcmsiv(uint8_t* key, uint8_t* i, uint8_t* p, uint8_t* a, uint8_t* c,
size_t np, size_t na, char* r)
{
char sk[2 * AES_KEY_SIZE + 1], si[25], sp[0x100], sc[0x100], sa[0x100], msg[30];
char sk[65], si[25], sp[0x100], sc[0x100], sa[0x100], msg[30];
uint8_t tmp[0x90], v = 0;
strcpy(msg, "passed the test");
GCM_SIV_encrypt(key, i, p, np, a, na, tmp, tmp + np);
GCM_SIV_encrypt(key, i, a, na, p, np, tmp);
if (memcmp(c, tmp, np + 16))
{
strcpy(msg, "encrypt failure");
v = 1;
}
memset(tmp, 0xcc, sizeof tmp);
*sk = GCM_SIV_decrypt(key, i, c, np, a, na, 16, tmp);
if (*sk || memcmp(p, tmp, np))
*r = GCM_SIV_decrypt(key, i, a, na, c, np, tmp);
if (*r || memcmp(p, tmp, np))
{
sprintf(msg, "%sdecrypt failure", v ? "encrypt & " : "");
strcat(strcpy(msg, v ? "encrypt & " : ""), "decrypt failure");
v |= 2;
}
bytes2str(key, sk, AES_KEY_SIZE);
bytes2str(i, si, 12);
bytes2str(key, sk, AES_KEYLENGTH);
bytes2str(i, si, SIVGCM_NONCE_LEN);
bytes2str(p, sp, np);
bytes2str(a, sa, na);
bytes2str(c, sc, np + 16);
bytes2str(c, sc, np + SIVGCM_TAG_LEN);
sprintf(r, "%s\nK: %s\ni: %s\nP: %s\nA: %s\nC: %s", msg, sk, si, sp, sa, sc);
return v;
}
static void aes_gcmsiv_test(FILE** files, unsigned* count)
void aes_gcmsiv_test(FILE** files, unsigned* count)
{
const char *linehdr[] = GCMSIV_HEADLINES;
const char* head[] = GCMSIV_HEADLINES;
char buffer[0x400], *value = NULL;
size_t s[5] = { 0 };
uint8_t key[AES_KEY_SIZE], iv[12], p[80], c[96], a[80], j, n = 0;
uint8_t key[32], iv[12], p[80], c[96], a[80], h, e = 0;
while (fgets(buffer, sizeof buffer, *files) != NULL)
{
buffer[ strcspn(buffer, "\n") ] = 0;
if (strlen(buffer) < 4) continue;
for (j = 0; j < 5; j++)
{
if (strncmp(buffer, linehdr[j], strlen(linehdr[j])) == 0)
for (h = strlen(buffer) < 4 ? 5 : 0; h < 5; ++h)
{
if (strncmp(buffer, head[h], strlen(head[h])) != 0) continue;
value = strrchr(buffer, ' ') + 1;
s[j] = strlen(value) / 2;
n += j > 2;
break;
}
}
switch (j)
s[h] = strlen(value) / 2;
switch (h)
{
case 0:
if (s[0] == AES_KEY_SIZE) str2bytes(value, key);
str2bytes(value, key);
break;
case 1:
if (s[1] == 12) str2bytes(value, iv);
str2bytes(value, iv);
break;
case 2:
str2bytes(value, a);
@@ -82,20 +76,21 @@ static void aes_gcmsiv_test(FILE** files, unsigned* count)
str2bytes(value, c);
break;
}
if (n == 2)
{
if (s[0] == AES_KEY_SIZE)
{
n = verifygcmsiv(key, iv, p, a, c, s[3], s[2], buffer);
fprintf(files[2 - !n], "%s\n", buffer); /* save the log */
++count[0];
if (n & 1) ++count[1];
if (n & 2) ++count[2];
e += (h == 3 || h == 4);
}
n = 0;
if (e == 2)
{
if (s[0] == AES_KEYLENGTH)
{
e = verifygcmsiv(key, iv, p, a, c, s[3], s[2], buffer);
fprintf(files[2 - !e], "%s\n", buffer); /* save the log */
++count[0];
if (e & 1) ++count[1];
if (e & 2) ++count[2];
}
e = 0;
}
}
}
#endif
#endif /* header guard */

View File

@@ -2,39 +2,38 @@
==============================================================================
Name : aes_testvectors_OCB.h
Author : polfosol
Version : 1.1.0.0
Version : 1.2.0.0
Copyright : copyright © 2024 - polfosol
Description : checking the test vectors for AES-OCB
==============================================================================
*/
#ifndef _TESTING_OCB_H_
#include "aes_testvectors.h"
#if defined(_TESTING_OCB_H_) ^ defined(OCB_TEST_FILE)
#define _TESTING_OCB_H_
#include "aes_testvectors.h"
#ifdef OCB_TEST_FILE
static int verifyocb(uint8_t* key, uint8_t* i, uint8_t* p, uint8_t* a, uint8_t* c,
int verifyocb(uint8_t* key, uint8_t* i, uint8_t* p, uint8_t* a, uint8_t* c,
size_t np, size_t na, uint8_t err, char* r)
{
char sk[2 * AES_KEY_SIZE + 1], si[31], sp[0x100], sc[0x100], sa[0x100], msg[30];
char sk[65], si[31], sp[0x100], sc[0x100], sa[0x100], msg[30];
uint8_t tmp[0x90], v = 0;
strcpy(msg, "passed the test");
AES_OCB_encrypt(key, i, p, np, a, na, tmp, tmp + np);
AES_OCB_encrypt(key, i, a, na, p, np, tmp);
if (memcmp(c, tmp, np + OCB_TAG_LEN) && !err)
{
strcpy(msg, "encrypt failure");
v = 1;
}
memset(tmp, 0xcc, sizeof tmp);
*sk = AES_OCB_decrypt(key, i, c, np, a, na, OCB_TAG_LEN, tmp) && !err;
if (*sk || memcmp(p, tmp, np))
*r = AES_OCB_decrypt(key, i, a, na, c, np, tmp);
if (*r && !err || memcmp(p, tmp, np))
{
sprintf(msg, "%sdecrypt failure", v ? "encrypt & " : "");
strcat(strcpy(msg, v ? "encrypt & " : ""), "decrypt failure");
v |= 2;
}
bytes2str(key, sk, AES_KEY_SIZE);
bytes2str(key, sk, AES_KEYLENGTH);
bytes2str(i, si, OCB_NONCE_LEN);
bytes2str(p, sp, np);
bytes2str(a, sa, na);
@@ -43,34 +42,32 @@ static int verifyocb(uint8_t* key, uint8_t* i, uint8_t* p, uint8_t* a, uint8_t*
return v;
}
static void aes_ocb_test(FILE** files, unsigned* count)
void aes_ocb_test(FILE** files, unsigned* count)
{
const char *linehdr[] = OCB_HEADLINES;
const char* head[] = OCB_HEADLINES;
char buffer[0x800], *value = NULL;
size_t s[7] = { 0 };
uint8_t key[AES_KEY_SIZE], tmp[AES_KEY_SIZE], iv[OCB_NONCE_LEN];
uint8_t j, p[0x80], c[0x90], a[0x80], t[16], r = 1;
uint8_t h, e, key[2 * AES_KEYLENGTH], iv[16], p[0x80], c[0x90], a[0x80];
while (fgets(buffer, sizeof buffer, *files) != NULL)
{
buffer[ strcspn(buffer, "\n") ] = 0;
if (strlen(buffer) < 4) continue;
for (j = 0; j < 7; j++)
for (h = strlen(buffer) < 4 ? 7 : 0; h < 7; ++h)
{
if (strncmp(buffer, linehdr[j], strlen(linehdr[j])) == 0)
if (strncmp(buffer, head[h], strlen(head[h])) == 0)
{
value = strrchr(buffer, ' ') + 1;
s[j] = strlen(value) / 2;
s[h] = strlen(value) / 2;
break;
}
}
switch (j)
switch (h)
{
case 0:
if (s[0] == AES_KEY_SIZE) str2bytes(value, tmp);
if (s[0] == AES_KEYLENGTH) str2bytes(value, key + *s);
break;
case 1:
if (s[1] == OCB_NONCE_LEN) str2bytes(value, iv);
str2bytes(value, iv);
break;
case 2:
str2bytes(value, a);
@@ -82,30 +79,26 @@ static void aes_ocb_test(FILE** files, unsigned* count)
str2bytes(value, c);
break;
case 5:
s[5] -= OCB_TAG_LEN;
str2bytes(value, t);
str2bytes(value, c + sizeof p);
break;
case 6:
j = strstr(value, "ERROR") - value;
j = 7 + (j > 0 && j < 0x100);
h = strstr(value, "ERROR") != NULL ? 8 : 0;
break;
}
if (j == 0 || j > 7)
if (h % 8 == 0 && s[0] == AES_KEYLENGTH)
{
if (s[0] == AES_KEY_SIZE && s[1] == OCB_NONCE_LEN && !s[5] && !r)
if (s[1] == OCB_NONCE_LEN && s[5] == OCB_TAG_LEN)
{
memcpy(c + s[3], t, OCB_TAG_LEN); /* put tag at the end */
r = verifyocb(key, iv, p, a, c, s[3], s[2], j, buffer);
fprintf(files[2 - !r], "%s\n", buffer); /* save the log */
memmove(c + s[4], c + sizeof p, s[5]); /* tag appended */
e = verifyocb(key, iv, p, a, c, s[3], s[2], h, buffer);
fprintf(files[2 - !e], "%s\n", buffer); /* save the log */
++count[0];
if (r & 1) ++count[1];
if (r & 2) ++count[2];
if (e & 1) ++count[1];
if (e & 2) ++count[2];
}
memcpy(key, tmp, sizeof key);
r = 0;
memcpy(key, key + *s, s[0]);
}
}
}
#endif
#endif /* header guard */

View File

@@ -2,64 +2,67 @@
==============================================================================
Name : aes_testvectors_POLY1305.h
Author : polfosol
Version : 1.1.0.0
Version : 1.2.0.0
Copyright : copyright © 2024 - polfosol
Description : checking the test vectors for AES-POLY1305
==============================================================================
*/
#ifndef _TESTING_POLY1305_H_
#include "aes_testvectors.h"
#if defined(_TESTING_POLY1305_H_) ^ defined(POLY_TEST_FILE)
#define _TESTING_POLY1305_H_
#include "aes_testvectors.h"
#ifdef POLY_TEST_FILE
static int verifypoly(uint8_t* key, uint8_t* non, uint8_t* d, uint8_t* m,
int verifypoly(uint8_t* key, uint8_t* non, uint8_t* d, uint8_t* m,
size_t nd, char* r)
{
char sk[2 * AES_KEY_SIZE + 33], smac[33], msg[30];
char sk[2 * AES_KEYLENGTH + 33], smac[33], msg[30];
uint8_t tmp[16], v = 0;
strcpy(msg, "passed the test");
AES_Poly1305(key, non, d, nd, tmp);
if ((v = memcmp(m, tmp, 16)) != 0) strcpy(msg, "failed");
bytes2str(key, sk, AES_KEY_SIZE + 16);
bytes2str(key, sk, AES_KEYLENGTH + 16);
bytes2str(m, smac, 16);
sprintf(r, "%s\nK: %s\npoly: %s\n", msg, sk, smac);
return v;
}
static void aes_poly1305_test(FILE** files, unsigned* count)
void aes_poly1305_test(FILE** files, unsigned* count)
{
const char *linehdr[] = POLY_HEADLINES;
char buffer[0x20100], *value = NULL;
const char* head[] = POLY_HEADLINES;
size_t s[4] = { 0 };
uint8_t j, n = 0, key[AES_KEY_SIZE + 16], nc[16], d[0x10100], m[16];
uint8_t h, *d, e = 0, key[AES_KEYLENGTH + 16], n[16], m[16];
char *value = NULL, *buffer;
count[2] = ~0U;
while (fgets(buffer, sizeof buffer, *files) != NULL)
if ((buffer = malloc(LINES_MAX_LEN / 2 * 3)) == NULL)
{
printf("Memory allocation failed.\n");
return;
}
while (fgets(buffer, LINES_MAX_LEN, *files) != NULL)
{
buffer[ strcspn(buffer, "\n") ] = 0;
if (strlen(buffer) < 4) continue;
for (j = 0; j < 4; j++)
for (h = strlen(buffer) < 4 ? 4 : 0; h < 4; ++h)
{
if (strncmp(buffer, linehdr[j], strlen(linehdr[j])) == 0)
if (strncmp(buffer, head[h], strlen(head[h])) == 0)
{
value = strrchr(buffer, ' ') + 1;
s[j] = strlen(value) / 2;
n += j > 1;
d = (uint8_t*) &buffer[LINES_MAX_LEN];
s[h] = strlen(value) / 2;
e += (h == 2 || h == 3);
break;
}
}
switch (j)
switch (h)
{
case 0:
if (s[0] == AES_KEY_SIZE + 16) str2bytes(value, key);
if (s[0] == sizeof key) str2bytes(value, key);
break;
case 1:
str2bytes(value, nc);
str2bytes(value, n);
break;
case 2:
str2bytes(value, d);
@@ -68,19 +71,19 @@ static void aes_poly1305_test(FILE** files, unsigned* count)
str2bytes(value, m);
break;
}
if (n == 2)
if (e == 2)
{
if (s[0] == AES_KEY_SIZE + 16)
if (s[0] == sizeof key)
{
n = verifypoly(key, nc, d, m, s[2], buffer);
fprintf(files[2 - !n], "%s\n", buffer); /* save the log */
e = verifypoly(key, n, d, m, s[2], buffer);
fprintf(files[2 - !e], "%s\n", buffer); /* save the log */
++count[0];
if (n) ++count[1];
count[1] += e != 0;
}
n = 0;
e = 0;
}
}
free(buffer);
}
#endif
#endif /* header guard */

View File

@@ -2,22 +2,21 @@
==============================================================================
Name : aes_testvectors_XTS.h
Author : polfosol
Version : 1.1.0.0
Version : 1.2.0.0
Copyright : copyright © 2024 - polfosol
Description : checking the test vectors for AES-XTS
==============================================================================
*/
#ifndef _TESTING_XTS_H_
#include "aes_testvectors.h"
#if defined(_TESTING_XTS_H_) ^ defined(XTS_TEST_FILE)
#define _TESTING_XTS_H_
#include "aes_testvectors.h"
#ifdef XTS_TEST_FILE
static int verifyxts(uint8_t* key, uint8_t* i, uint8_t* p, uint8_t* c,
int verifyxts(uint8_t* key, uint8_t* i, uint8_t* p, uint8_t* c,
size_t np, char* r)
{
char sk[4 * AES_KEY_SIZE + 1], si[33], sp[0x80], sc[0x80], msg[30];
char sk[4 * AES_KEYLENGTH + 1], si[33], sp[0x80], sc[0x80], msg[30];
uint8_t tmp[0x80], v = 0;
strcpy(msg, "passed the test");
@@ -31,10 +30,10 @@ static int verifyxts(uint8_t* key, uint8_t* i, uint8_t* p, uint8_t* c,
AES_XTS_decrypt(key, i, c, np, tmp);
if (memcmp(p, tmp, np))
{
sprintf(msg, "%sdecrypt failure", v ? "encrypt & " : "");
strcat(strcpy(msg, v ? "encrypt & " : ""), "decrypt failure");
v |= 2;
}
bytes2str(key, sk, 2 * AES_KEY_SIZE);
bytes2str(key, sk, 2 * AES_KEYLENGTH);
bytes2str(i, si, 16);
bytes2str(p, sp, np);
bytes2str(c, sc, np);
@@ -42,31 +41,30 @@ static int verifyxts(uint8_t* key, uint8_t* i, uint8_t* p, uint8_t* c,
return v;
}
static void aes_xts_test(FILE** files, unsigned* count)
void aes_xts_test(FILE** files, unsigned* count)
{
const char *linehdr[] = XTS_HEADLINES;
const char* head[] = XTS_HEADLINES;
char buffer[0x800], *value = NULL;
size_t s = 0, sk = 0;
uint8_t j, n = 0, key[2 * AES_KEY_SIZE], iv[16], p[0x80], c[0x80], ul[2];
size_t s[5] = { 0 };
uint8_t h, e = 0, key[2 * AES_KEYLENGTH], iv[16], p[0x80], c[0x80];
while (fgets(buffer, sizeof buffer, *files) != NULL)
{
buffer[ strcspn(buffer, "\n") ] = 0;
if (strlen(buffer) < 4) continue;
for (j = 0; j < 5; j++)
for (h = strlen(buffer) < 4 ? 5 : 0; h < 5; ++h)
{
if (strncmp(buffer, linehdr[j], strlen(linehdr[j])) == 0)
if (strncmp(buffer, head[h], strlen(head[h])) == 0)
{
value = strrchr(buffer, ' ') + 1;
n += (j == 2 || j == 3);
s[h] = strlen(value) / 2;
e += (h == 2 || h == 3);
break;
}
}
switch (j)
switch (h)
{
case 0:
sk = strlen(value) / 4;
if (sk == AES_KEY_SIZE) str2bytes(value, key);
if (s[0] == sizeof key) str2bytes(value, key);
break;
case 1:
str2bytes(value, iv);
@@ -78,24 +76,22 @@ static void aes_xts_test(FILE** files, unsigned* count)
str2bytes(value, c);
break;
case 4:
str2bytes(value, ul);
s = (ul[0] >> 4) *100 + (ul[0] & 15) *10 + (ul[1] >> 4);
for (s[4] = 0; *value; s[4] *= 10) s[4] += *value++ - '0';
break;
}
if (n == 2)
if (e == 2)
{
if (sk == AES_KEY_SIZE && s % 8 == 0)
if (s[0] == sizeof key && s[4] == s[2] * 80)
{
n = verifyxts(key, iv, p, c, s / 8, buffer);
fprintf(files[2 - !n], "%s\n", buffer); /* save the log */
e = verifyxts(key, iv, p, c, s[2], buffer);
fprintf(files[2 - !e], "%s\n", buffer); /* save the log */
++count[0];
if (n & 1) ++count[1];
if (n & 2) ++count[2];
if (e & 1) ++count[1];
if (e & 2) ++count[2];
}
n = 0;
e = 0;
}
}
}
#endif
#endif /* header guard */