Added EAX-prime & SIV

This commit is contained in:
polfosol
2022-10-01 14:21:38 +03:30
commit 04c9b232d1
14 changed files with 11107 additions and 0 deletions

201
LICENSE Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright © 2022 - polfosol
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

44
README.md Normal file
View File

@@ -0,0 +1,44 @@
# µAES
A minimalist ANSI-C compatible code for most of the AES-related algorithms.
This library is a highly flexible, all-in-one implementation of different AES encryption schemes and block ciphers modes. Before you continue, please keep in mind that, most security experts strongly warn *against* implementing your own version of AES—or other ciphering algorithms; AND THEY ARE ABSOLUTELY RIGHT!
Everyone who is becoming familiar with cryptography, should first sign [Jeff Moser's](https://www.moserware.com/2009/09/stick-figure-guide-to-advanced.html) so-called "Foot Shooting Prevention Agreement". I have put a copy of it at the bottom of this page.
With that in mind, I shall say that the main purpose of developing µAES was purely educational. I learned a lot during writing these codes and I hope that somebody, some day, would gain a bit of knowledge from it.
## Features
* **Comprehensive —** supports any form of the AES standard with all different key sizes, i.e. you can use AES-128 or AES-192 or AES-256 simply by setting a macro.
* **All in one —** all popular (and some unpopular) blocks ciphering modes of the AES are implemented into a single file; such as **_ECB_**, **_CBC_**, **_CFB_**, **_OFB_**, **_CTR_**, **_XTS_**, **_KW_** / **_KWA_**, FPE, **_GCM_**, **_CCM_**, **_OCB_**, **_EAX_**, **_SIV_**, and GCM-SIV.
* **Clear and readable code —** hopefully, the code is written in a layman-friendly way. Lots of comments are added along the way to make its purpose more understandable. Also the code styling is a bit different, and IMO more eye-catching, than what you might see in other implementations.
* **Flexible —** many features of µAES are controllable by macros, so that you can just pick up what you need and disable the unnecessary parts. These macros are defined in the header file `micro_aes.h` and comments are added for each of them to explain what they represent. *Please read those comments carefully before using the code*.
* **Lightweight —** the API has very little memory footprint and compiled code size. In my own tests and benchmarks, the amount of RAM used by the functions didn't exceed a few hundred bytes in most extreme cases. I might update this repo later with some of those benchmarks, and you are also cheerfully welcome to run yours.
Furthermore, the ROM space of µAES is optimized as much as possible. For example, if you disable all other macros and just stick with the GCM, the compiled code size will be less than 3.5KB on an x86 machine for either AES-128-GCM or AES-256-GCM.
* **Fast —** the encryption or decryption speed is often an order of magnitude higher than some .net based implementations and even C++ libraries. Since code simplicity and portability was a main concern, paralellization or advanced CPU optimizations are not a feature of µAES, which might affect its overall speed.
Anyway, speed is not always a blessing in cryptography and even sometimes slower codes turn out to be more secure. One must be wary of those speedups that make the code more susceptible to [timing attacks](https://en.wikipedia.org/wiki/Timing_attack).
* **Portable —** µAES is all-in-one with no dependencies on any other library. It is fully compatible with ANSI-C or C89 standard which, combined with its small size, makes it a competent candidate for embedded systems and mini applications.
You can even compile it with [Tiny C Compiler](https://bellard.org/tcc/):
```
tcc -c main.c -o main.o
tcc -c micro_aes.c -o micro_aes.o
tcc -o micro_aes.exe main.o micro_aes.o
```
## Remarks
For the sake of simplicity, it is assumed that the input parameters of the functions are well defined, and the user knows what they're doing. As a result, many error checks are just skipped. Obviously, this is a very naive and sometimes dangerous assumption. One must be aware that in a serious application, anything can be fed into the functions and they must take all the necessary precautions for erroneous parameters.
µAES is heavily influenced by [kokke's tiny-AES](https://github.com/kokke/tiny-AES-c) library, but I have made some modifications which makes it a bit smaller and faster. I shall give kudos to their great effort which paved the way for many other branches.
All the contents of this repository (except the ones that I didn't write!) are subject to the terms of Apache 2.0 license.
Copyright © 2022 - polfosol
![The foot-shooting prevention agreement taken from Jeff Moser's blog](https://i.stack.imgur.com/SoY7x.png)

48
codeblocks.cbp Normal file
View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="micro_aes" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/micro_aes" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Debug/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-pedantic" />
<Add option="-ansi" />
<Add option="-Og" />
<Add option="-g" />
</Compiler>
</Target>
<Target title="Release">
<Option output="bin/Release/micro_aes" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Release/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-Os" />
<Add option="-pedantic" />
<Add option="-ansi" />
</Compiler>
<Linker>
<Add option="-s" />
</Linker>
</Target>
</Build>
<Compiler>
<Add option="-Wall" />
</Compiler>
<Unit filename="main.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="micro_aes.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="micro_aes.h" />
<Extensions />
</Project>
</CodeBlocks_project_file>

284
main.c Normal file
View File

@@ -0,0 +1,284 @@
/*
==============================================================================
Name : main.c
Author : polfosol
Version : 8.0.0.0
Copyright : copyright © 2022 - polfosol
Description : test vectors for µAES ™ library, mostly generated by Crypto++ ®
==============================================================================
*/
#include "micro_aes.h"
#define TestStringSize 114 /* hex characters in plain-text */
#define BuffL ((TestStringSize / 2 + 31) & ~15)
static const char
*masterKey = "0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F",
*secretKey = "0011223344556677 8899AABBCCDDEEFF 0001020304050607 08090A0B0C0D0E0F",
*cipherKey = "279fb74a7572135e 8f9b8ef6d1eee003 69c4e0d86a7b0430 d8cdb78070b4c55a",
*iVec = "8ea2b7ca516745bf eafc49904b496089",
*plainText = "c9f775baafa36c25 cd610d3c75a482ea dda97ca4864cdfe0 6eaf70a0ec0d7191\
d55027cf8f900214 e634412583ff0b47 8ea2b7ca516745bf ea",
#if AES_KEY_LENGTH == 16
*ecbcipher = "5d00c273f8b2607d a834632dcbb521f4 697dd4ab20bb0645 32a6545e24e33ae9\
f545176111f93773 dbecd262841cf83b 10d145e71b772cf7 a12889cda84be795",
#if !CTS /* ↑↑ and ↓↓ both zero-padded plain text. */
*cbccipher = "65c48fdf9fbd6261 28f2d8bac3f71251 75e7f4821fda0263 70011632779d7403\
7e9e2d298e154bc4 2dc7a9bc419b915d c119ef461ac4e1bc 8a7e36bf92b3b3d1",
#else
*cbccipher = "65c48fdf9fbd6261 28f2d8bac3f71251 75e7f4821fda0263 70011632779d7403\
c119ef461ac4e1bc 8a7e36bf92b3b3d1 7e9e2d298e154bc4 2d",
#endif
*cfbcipher = "edab3105e673bc9e b9102539a9f457bc 245c14e1bff81b5b 4a4a147c988cb0a6\
3f9c56525efbe64a 876ad1d761d3fc93 59fb4f5b2354acd4 90",
*ofbcipher = "edab3105e673bc9e b9102539a9f457bc d28c8e4c92995f5c d9426926be1e775d\
e22b8ce4d0278b18 181b8bec93b9726f 959aa5d701d46102 f0",
#if ~INIT_CTR_VALUE == 0
*ctrcipher = "edab3105e673bc9e b9102539a9f457bc f2e2606dfa3f93c5 c51b910a89cddb67\
191a118531ea0427 97626c9bfd370426 fdf3f59158bf7d4d 43",
#else
*ctrcipher = "6c6bae886c235d8c 7997d45c1bf0bca2 48b4bca9eb396d1b f6945e5b7a4fc10f\
488cfe76fd5eaeff 2b8fb469f78fa61e 285e4cf9b9aee3d0 a8",
#endif
*xtscipher = "10f9301a157bfceb 3eb9e7bd38500b7e 959e21ba3cc1179a d7f7d7d99460e695\
5e8bcb177571c719 6de58ff28c381913 e7c82d0adfd90c45 ca",
*ccmcipher = "d2575123438338d7 0b2955537fdfcf41 729870884e85af15 f0a74975a72b337d\
04d426de87594b9a be3e6dcf07f21c99 db3999f81299d302 ad1e5ba683e9039a\
5483685f1bd2c3fa 3b", /* <---- with 16 bytes tag */
*sivcipher = "d93703e9600529dc c5dc2fca84a46a61 20817b1954793c52 3bbaab1607d0c6fc\
932b51c56aa98861 ddfd9637a52fa786 f1b2e1290525812d 247cc1cc5f2bccf2\
d9a81d004f16ee64 c4", /* 16 bytes i.v. PREPENDED */
*gcmcipher = "5ceab5b7c2d6dede 555a23c7e3e63274 4075a51df482730b a31485ec987ddcc8\
73acdcfc6759a47b a424d838e7c0cb71 b9a4d8f4572e2141 18c8ab284ca845c1\
4394618703cddf3a fb", /* <---- with 16 bytes tag */
*ocbcipher = "fc254896eb785b05 dd87f240722dd935 61f5a0ef6aff2eb6 5953da0b26257ed0\
d69cb496e9a0cb1b f646151aa07e629a 28d99f0ffd7ea753 5c39f440df33c988\
c55cbcc8ac086ffa 23", /* <---- with 16 bytes tag */
#if EAXP
*eaxcipher = "f516e9c20069292c c51ba8b6403ddedf 5a34798f62187f58 d723fa33573fd80b\
f08ffbb09dadbd0b 6fa4812ca4bb5e6d db9a384943b36690 e81738a7a1",
#else /* ↑↑↑↑ with 4 bytes tag */
*eaxcipher = "4e2fa1bef9ffc23f 6965ee7135981c91 af9bfe97a6b13c01 b8b99e114dda2391\
50661c618335a005 47cca55a8f22fbd5 ed5ab4b4a17d0aa3 29febd14ef271bae\
986810a504f01ec6 02", /* <---- with 16 bytes tag */
#endif
*gsvcipher = "XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX\
XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX\
XXXXXXXXXXXXXXXX XX",
*wrapped = "1FA68B0A8112B447 AEF34BD8FB5A7B82 9D3E862371D2CFE5";
#elif AES_KEY_LENGTH == 24 /* ↓↓↓↓ PKCS#7 is enabled */
*ecbcipher = "af1893f0fbb09a43 7f6b0fd4f4977890 7bb85cccf1e9d2e3 ebe5bae935107868\
c6d72cb2ca375c12 ce6b6b1141141fd0 d268d14db351d680 5aabb99427341da9",
*wrapped = "031D33264E15D332 68F24EC260743EDC E1C6C7DDEE725A93 6BA814915C6762D2";
#else
*xtscipher = "40bfcc14845b1bb4 15dd13abf1e6f89d 3bfd794cf6655ffd 14c0d7e4177eeaf4\
5dd95f05663fcfb4 47671154a91b9d00 d1bd7a35c14c7410 9a",
*wrapped = "28C9F404C4B810F4 CBCCB35CFB87F826 3F5786E2D80ED326 CBC7F0E71A99F43B\
FB988B9B7A02DD21"; /* <---- it is in RFC-3394 */
#endif
static void str2bytes(const char* str, uint8_t* bytes)
#define char2num(c) (c > '9' ? (c & 7) + 9 : c & 0xF)
{
size_t i, j;
for (i = 0, j = ~0; str[i]; ++i)
{
if (str[i] < '0' || str[i] > 'f') continue;
if (j++ & 1) bytes[j / 2] = char2num(str[i]) << 4;
else bytes[j / 2] |= char2num(str[i]);
}
}
#include <stdio.h>
#include <string.h>
static void check(const char* method, uint8_t* result, uint8_t* expected, size_t size)
{
int c = memcmp(expected, result, size);
printf("AES-%d %s: %s\n", AES_KEY_LENGTH*8, method, c ? "FAILED :(" : "PASSED!");
memset(result, 0xcc , BuffL);
}
int main()
{
uint8_t mainKey[32], key[64], iv[16], input[BuffL - 16], test[BuffL], output[BuffL],
*a = key, sa = sizeof mainKey - 1, st = TestStringSize / 2;
str2bytes(cipherKey, key);
str2bytes(secretKey, key + 32);
str2bytes(masterKey, mainKey);
str2bytes(iVec, iv);
str2bytes(plainText, input);
printf("Test results...\n");
#if !BLOCK_CIPHERS_MODES
#if AES_KEY_LENGTH > 16
a = input + (AES_KEY_LENGTH == 32) * 32;
memcpy(input + 48, iv, 16);
#endif
memcpy(test, a, 32);
memcpy(test + 32, mainKey, 16);
memcpy(test + 48, key + 32, 16);
AES_Cipher(key + 32, 'E', mainKey, output);
AES_Cipher(mainKey, 'E', key + 32, output + 16);
AES_Cipher(key + 32, 'D', a, output + 32);
AES_Cipher(mainKey, 'D', a + 16, output + 48);
check("encryption & decryption", output, test, 64);
#endif
#if ECB && AES_KEY_LENGTH != 32
str2bytes(ecbcipher, test);
AES_ECB_encrypt(key, input, st, output);
check("ECB encryption", output, test, sizeof input);
AES_ECB_decrypt(key, test, sizeof input, output);
check("ECB decryption", output, input, st);
#endif
#if CBC && AES_KEY_LENGTH == 16
str2bytes(cbccipher, test);
AES_CBC_encrypt(key, iv, input, st, output);
check("CBC encryption", output, test, st);
AES_CBC_decrypt(key, iv, test, CTS ? st : sizeof input, output);
check("CBC decryption", output, input, st);
#endif
#if CFB && AES_KEY_LENGTH == 16
str2bytes(cfbcipher, test);
AES_CFB_encrypt(key, iv, input, st, output);
check("CFB encryption", output, test, st);
AES_CFB_decrypt(key, iv, test, st, output);
check("CFB decryption", output, input, st);
#endif
#if OFB && AES_KEY_LENGTH == 16
str2bytes(ofbcipher, test);
AES_OFB_encrypt(key, iv, input, st, output);
check("OFB encryption", output, test, st);
AES_OFB_decrypt(key, iv, test, st, output);
check("OFB decryption", output, input, st);
#endif
#if CTRNA && AES_KEY_LENGTH == 16
str2bytes(ctrcipher, test);
AES_CTR_encrypt(key, iv, input, st, output);
check("CTR encryption", output, test, st);
AES_CTR_decrypt(key, iv, test, st, output);
check("CTR decryption", output, input, st);
#endif
#if XTS && AES_KEY_LENGTH != 24
str2bytes(xtscipher, test);
AES_XTS_encrypt(key, iv, input, st, output);
check("XTS encryption", output, test, st);
AES_XTS_decrypt(key, iv, test, st, output);
check("XTS decryption", output, input, st);
#endif
a = mainKey + 1; /* aad */
#if GCM && AES_KEY_LENGTH == 16
str2bytes(gcmcipher, test);
AES_GCM_encrypt(key, iv, input, st, a, sa, output, output + st);
check("GCM encryption", output, test, st + 16);
AES_GCM_decrypt(key, iv, test, st, a, sa, test + st, 16, output);
check("GCM decryption", output, input, st);
#endif
#if CCM && AES_KEY_LENGTH == 16
str2bytes(ccmcipher, test);
AES_CCM_encrypt(key, iv, input, st, a, sa, output, output + st);
check("CCM encryption", output, test, st + CCM_TAG_SIZE);
AES_CCM_decrypt(key, iv, test, st, a, sa, test + st, CCM_TAG_SIZE, output);
check("CCM decryption", output, input, st);
#endif
#if OCB && AES_KEY_LENGTH == 16
str2bytes(ocbcipher, test);
AES_OCB_encrypt(key, iv, input, st, a, sa, output, output + st);
check("OCB encryption", output, test, st + OCB_TAG_SIZE);
AES_OCB_decrypt(key, iv, test, st, a, sa, test + st, OCB_TAG_SIZE, output);
check("OCB decryption", output, input, st);
#endif
#if SIV && AES_KEY_LENGTH == 16
str2bytes(sivcipher, test);
AES_SIV_encrypt(key, input, st, a, sa, output, output + 16);
check("SIV encryption", output, test, st + 16);
AES_SIV_decrypt(key, test + 16, st, a, sa, test, output);
check("SIV decryption", output, input, st);
#endif
#if EAX && AES_KEY_LENGTH == 16
str2bytes(eaxcipher, test);
#if EAXP
AES_EAX_encrypt(key, a, sa, input, st, output, output + st);
check("EAX encryption", output, test, st + 4);
AES_EAX_decrypt(key, a, sa, test, st, output);
#else
AES_EAX_encrypt(key, iv, sizeof iv, input, st, a, sa, output, output + st);
check("EAX encryption", output, test, st + 16);
AES_EAX_decrypt(key, iv, sizeof iv, test, st, a, sa, test + st, 16, output);
#endif
check("EAX decryption", output, input, st);
#endif
#if GCM_SIV && AES_KEY_LENGTH == 16
str2bytes(gsvcipher, test);
check("GCM-SIV encryption", output, test, st + 16);
check("GCM-SIV decryption", output, input, st);
#endif
#if KWA
str2bytes(wrapped, test);
AES_KEY_wrap(mainKey, key + 32, AES_KEY_LENGTH, output);
check("key wrapping ", output, test, AES_KEY_LENGTH + 8);
AES_KEY_unwrap(mainKey, test, AES_KEY_LENGTH + 8, output);
check("key unwrapping", output, key + 32, AES_KEY_LENGTH);
#endif
/** a template for "OFFICIAL TEST VECTORS": */
#if OCB && EAX && SIV && AES_KEY_LENGTH == 16
printf("+-> Let's do some extra tests\n");
st = sa = 24; /* taken from RFC 7253: */
str2bytes("000102030405060708090A0B0C0D0E0F", key);
str2bytes("BBAA99887766554433221107", iv);
str2bytes("000102030405060708090A0B0C0D0E0F1011121314151617", a);
str2bytes("000102030405060708090A0B0C0D0E0F1011121314151617", input);
str2bytes("1CA2207308C87C010756104D8840CE1952F09673A448A122\
C92C62241051F57356D7F3C90BB0E07F", test);
AES_OCB_encrypt(key, iv, input, st, a, sa, output, output + st);
check("OCB encryption", output, test, st + OCB_TAG_SIZE);
AES_OCB_decrypt(key, iv, test, st, a, sa, test + st, OCB_TAG_SIZE, output);
check("OCB decryption", output, input, st);
#endif
#if SIV && AES_KEY_LENGTH == 16
st = 14; sa = 24; /* taken from RFC 5297: */
str2bytes("fffefdfc fbfaf9f8 f7f6f5f4 f3f2f1f0\
f0f1f2f3 f4f5f6f7 f8f9fafb fcfdfeff", key);
str2bytes("10111213 14151617 18191a1b 1c1d1e1f\
20212223 24252627", a);
str2bytes("11223344 55667788 99aabbcc ddee", input);
str2bytes("85632d07 c6e8f37f 950acd32 0a2ecc93\
40c02b96 90c4dc04 daef7f6a fe5c", test);
AES_SIV_encrypt(key, input, st, a, sa, output, output + 16);
check("SIV encryption", output, test, st + 16);
AES_SIV_decrypt(key, test + 16, st, a, sa, test, output);
check("SIV decryption", output, input, st);
#endif
#if EAX && AES_KEY_LENGTH == 16
#if EAXP
st = 28; sa = 65; /* from Moise-Beroset-Phinney-Burns paper: */
str2bytes("10 20 30 40 50 60 70 80 90 a0 b0 c0 d0 e0 f0 00", mainKey);
str2bytes("a2 0e 06 0c 60 86 48 01 86 fc 2f 81 1c aa 4e 01\
a8 06 02 04 39 a0 0e bb ac 0f a2 0d a0 0b a1 09\
80 01 00 81 04 4b ce e2 c3 be 25 28 23 81 21 88\
a6 0a 06 08 2b 06 01 04 01 82 85 63 00 4b ce e2\
c3", test);
str2bytes("17 51 30 30 30 30 30 30 30 30 30 30 30 30 30 30\
30 30 30 30 30 30 00 00 03 30 00 01", input);
str2bytes("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(mainKey, test, sa, input, st, output, output + st);
check("EAX encryption", output, key, st + 4);
AES_EAX_decrypt(mainKey, test, sa, key, st, output);
#else
st = 12; sa = 8; /* from Bellare-Rogaway-Wagner 2004 paper: */
str2bytes("BD8E6E11475E60B268784C38C62FEB22", key);
str2bytes("6EAC5C93072D8E8513F750935E46DA1B", iv);
str2bytes("D4482D1CA78DCE0F", a);
str2bytes("4DE3B35C3FC039245BD1FB7D", input);
str2bytes("835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F", test);
AES_EAX_encrypt(key, iv, 16, input, st, a, sa, output, output + st);
check("EAX encryption", output, test, st + 16);
AES_EAX_decrypt(key, iv, 16, test, st, a, sa, test + st, 16, output);
#endif
check("EAX decryption", output, input, st);
#endif
return 0;
}

1806
micro_aes.c Normal file

File diff suppressed because it is too large Load Diff

437
micro_aes.h Normal file
View File

@@ -0,0 +1,437 @@
/*
==============================================================================
Name : micro_aes.h
Author : polfosol
Version : 8.0.0.0
Copyright : copyright © 2022 - polfosol
Description : μAES ™ is a minimalist all-in-one library for AES encryption
==============================================================================
*/
#ifndef _MICRO__AES_
#define _MICRO__AES_
/**----------------------------------------------------------------------------
You can use different AES algorithms by changing this macro. Default is AES-128
-----------------------------------------------------------------------------*/
#define AES___ 128 /* or 256 (or 192; not standardized in some modes) */
#define BLOCK_CIPHERS_MODES 1
/**----------------------------------------------------------------------------
AES block-cipher modes of operation. The following modes can be enabled/disabled
by setting their corresponding macros to TRUE (1) or FALSE (0).
-----------------------------------------------------------------------------*/
#if BLOCK_CIPHERS_MODES
#define ECB 1 /* electronic code-book (NIST SP 800-38A) */
#define CBC 1 /* cipher block chaining (NIST SP 800-38A) */
#define CFB 1 /* cipher feedback (NIST SP 800-38A) */
#define OFB 1 /* output feedback (NIST SP 800-38A) */
#define CTR 1 /* counter-block (NIST SP 800-38A) */
#define XEX 1 /* xor-encrypt-xor (NIST SP 800-38E) */
#define KWA 1 /* key wrap with authentication (NIST SP 800-38F) */
#define FPE 0 /* format-preserving encryption (NIST SP 800-38G) */
#endif
#if CTR
#define CTRNA 1 /* pure counter mode, with no authentication */
#define CCM 1 /* counter with CBC-MAC (RFC-3610 & SP 800-38C) */
#define GCM 1 /* Galois/counter mode with GMAC (NIST SP 800-38D) */
#define EAX 1 /* encrypt-authenticate-translate (ANSI C12.22) */
#define SIV 1 /* synthetic initialization vector (RFC-5297) */
#define GCM_SIV 0 /* nonce misuse-resistant AES-GCM (RFC-8452) */
#endif
#if CBC
#define CTS 1 /* ciphertext stealing (CS3: unconditional swap) */
#endif
#if XEX
#define XTS 1 /* XEX tweaked-codebook with ciphertext stealing */
#define OCB 1 /* offset codebook mode (RFC-7253) */
#endif
#if EAX
#define EAXP 0 /* EAX-prime, as specified by IEEE Std 1703 */
#endif
#if CCM || GCM || EAX || OCB || SIV || GCM_SIV
#define AEAD_MODES /* authenticated encryption with associated data. */
#endif
#if CFB || OFB || CTR || OCB
#define PARTIAL_BLOCK_PASS /* supports data units shorter than a full block. */
#endif
/**----------------------------------------------------------------------------
REFER TO THE BOTTOM OF THIS DOCUMENT FOR SOME EXPLANATIONS ABOUT THESE MACROS:
-----------------------------------------------------------------------------*/
#if ECB || CBC || XEX || KWA || !BLOCK_CIPHERS_MODES
#define DECRYPTION 1
#endif
#if ECB || (CBC && !CTS) || (XEX && !XTS)
#define AES_PADDING 0 /* other valid values: (1) PKCS#7 (2) IEC7816-4 */
#endif
#if CTR
#define INIT_CTR_VALUE 1 /* if set to ~0 a full block I.V is used in CTRNA. */
#define CTR_IV_SIZE 12 /* this value applies to the GCM mode as well. */
#endif
#if CCM
#define CCM_IV_SIZE 11 /* for 32-bit count (since one byte is reserved). */
#define CCM_TAG_SIZE 16
#endif
#if OCB
#define OCB_TAG_SIZE 16 /* again, please see the bottom of this document! */
#endif
/**----------------------------------------------------------------------------
If the length of the input cipher/plain text is 'always' less than 4KB, you can
enable this macro to save a few bytes in the compiled code. Which would be a
valid assumption for some embedded systems and small applications.
!>> Note: for key-wrapping, this limit is 42 blocks (336 bytes) of secret key.
-----------------------------------------------------------------------------*/
#define SMALL_CIPHER 0
#include <stddef.h>
typedef unsigned char uint8_t; /* C89 doesn't have <stdint.h> */
#if SMALL_CIPHER
typedef unsigned short size_T;
typedef unsigned char count_T;
#else
typedef size_t size_T;
typedef size_t count_T;
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**----------------------------------------------------------------------------
Encryption/decryption of a single block with Rijndael
-----------------------------------------------------------------------------*/
#if !BLOCK_CIPHERS_MODES
void AES_Cipher( const uint8_t* key, /* encryption/decryption key */
const char mode, /* encrypt: 'E', decrypt: 'D' */
const uint8_t* x, /* input block byte array */
uint8_t* y ); /* output block byte array */
#endif
/**----------------------------------------------------------------------------
Main functions for ECB-AES block ciphering
-----------------------------------------------------------------------------*/
#if ECB
void AES_ECB_encrypt( const uint8_t* key, /* encryption key */
const uint8_t* pText, /* plain text */
const size_T pTextLen, /* length of input plain text */
uint8_t* cText ); /* cipher-text buffer */
char AES_ECB_decrypt( const uint8_t* key, /* decryption key */
const uint8_t* cText, /* cipher text */
const size_T cTextLen, /* length of input cipher-text */
uint8_t* pText ); /* decrypted plain-text */
#endif /* ECB */
/**----------------------------------------------------------------------------
Main functions for CBC-AES block ciphering
-----------------------------------------------------------------------------*/
#if CBC
void AES_CBC_encrypt( const uint8_t* key, /* encryption key */
const uint8_t* iVec, /* initialization vector */
const uint8_t* pText, /* plain text */
const size_T pTextLen, /* length of input plain text */
uint8_t* cText ); /* cipher-text buffer */
char AES_CBC_decrypt( const uint8_t* key, /* decryption key */
const uint8_t* iVec, /* initialization vector */
const uint8_t* cText, /* cipher text */
const size_T cTextLen, /* length of input cipher-text */
uint8_t* pText ); /* decrypted plain-text */
#endif /* CBC */
/**----------------------------------------------------------------------------
Main functions for CFB-AES block ciphering
-----------------------------------------------------------------------------*/
#if CFB
void AES_CFB_encrypt( const uint8_t* key, /* encryption key */
const uint8_t* iVec, /* initialization vector */
const uint8_t* pText, /* plain text */
const size_T pTextLen, /* length of input plain text */
uint8_t* cText ); /* cipher-text buffer */
void AES_CFB_decrypt( const uint8_t* key, /* decryption key */
const uint8_t* iVec, /* initialization vector */
const uint8_t* cText, /* cipher text */
const size_T cTextLen, /* length of input cipher-text */
uint8_t* pText ); /* decrypted plain-text */
#endif /* CFB */
/**----------------------------------------------------------------------------
Main functions for OFB-AES block ciphering
-----------------------------------------------------------------------------*/
#if OFB
void AES_OFB_encrypt( const uint8_t* key, /* encryption key */
const uint8_t* iVec, /* initialization vector */
const uint8_t* pText, /* plain text */
const size_T pTextLen, /* length of input plain text */
uint8_t* cText ); /* cipher-text buffer */
void AES_OFB_decrypt( const uint8_t* key, /* decryption key */
const uint8_t* iVec, /* initialization vector */
const uint8_t* cText, /* cipher text */
const size_T cTextLen, /* length of input cipher-text */
uint8_t* pText ); /* decrypted plain-text */
#endif /* OFB */
/**----------------------------------------------------------------------------
Main functions for XTS-AES block ciphering
-----------------------------------------------------------------------------*/
#if XTS
char AES_XTS_encrypt( const uint8_t* keys, /* encryption key pair */
const uint8_t* unitId, /* tweak value (sector ID) */
const uint8_t* pText, /* plain text */
const size_T pTextLen, /* length of input plain text */
uint8_t* cText ); /* cipher-text buffer */
char AES_XTS_decrypt( const uint8_t* keys, /* decryption key pair */
const uint8_t* unitId, /* tweak value (sector ID) */
const uint8_t* cText, /* cipher text */
const size_T cTextLen, /* length of input cipher-text */
uint8_t* pText ); /* decrypted plain-text */
#endif /* XTS */
/**----------------------------------------------------------------------------
Main functions for CTR-AES block ciphering
-----------------------------------------------------------------------------*/
#if CTRNA
void AES_CTR_encrypt( const uint8_t* key, /* encryption key */
const uint8_t* iv, /* initialization vector/ nonce */
const uint8_t* pText, /* plain text */
const size_T pTextLen, /* length of input plain text */
uint8_t* cText ); /* cipher-text buffer */
void AES_CTR_decrypt( const uint8_t* key, /* decryption key */
const uint8_t* iv, /* initialization vector/ nonce */
const uint8_t* cText, /* cipher text */
const size_T cTextLen, /* length of input cipher-text */
uint8_t* pText ); /* decrypted plain-text */
#endif /* CTR */
/**----------------------------------------------------------------------------
Main functions for SIV-AES block ciphering
-----------------------------------------------------------------------------*/
#if SIV
void AES_SIV_encrypt( const uint8_t* keys, /* encryption key pair */
const uint8_t* pText, /* plain text */
const size_T pTextLen, /* length of input plain text */
const uint8_t* aData, /* added authentication data */
const size_T aDataLen, /* size of authentication data */
uint8_t* iv, /* synthesized init-vector */
uint8_t* cText ); /* cipher-text buffer */
char AES_SIV_decrypt( const uint8_t* keys, /* decryption key pair */
const uint8_t* cText, /* cipher text */
const size_T cTextLen, /* length of input cipher-text */
const uint8_t* aData, /* added authentication data */
const size_T aDataLen, /* size of authentication data */
const uint8_t* iv, /* provided init-vector */
uint8_t* pText ); /* decrypted plain-text */
#endif /* SIV */
/**----------------------------------------------------------------------------
Main functions for GCM-AES block ciphering
-----------------------------------------------------------------------------*/
#if GCM
void AES_GCM_encrypt( const uint8_t* key, /* encryption key */
const uint8_t* iv, /* initialization vector/ nonce */
const uint8_t* pText, /* plain text */
const size_T pTextLen, /* length of input plain text */
const uint8_t* aData, /* added authentication data */
const size_T aDataLen, /* size of authentication data */
uint8_t* cText, /* cipher-text buffer */
uint8_t* auTag ); /* message authentication tag */
char AES_GCM_decrypt( const uint8_t* key, /* decryption key */
const uint8_t* iv, /* initialization vector/ nonce */
const uint8_t* cText, /* cipher text */
const size_T cTextLen, /* length of input cipher-text */
const uint8_t* aData, /* added authentication data */
const size_T aDataLen, /* size of authentication data */
const uint8_t* auTag, /* authentication tag */
const uint8_t tagSize, /* size of tag (if any) */
uint8_t* pText ); /* decrypted plain-text */
#endif /* GCM */
/**----------------------------------------------------------------------------
Main functions for GCM-SIV-AES block ciphering
-----------------------------------------------------------------------------*/
#if GCM_SIV
void GCM_SIV_encrypt( const uint8_t* keys, /* encryption key pair */
);
char GCM_SIV_decrypt( const uint8_t* keys, /* decryption key pair */
uint8_t* pText ); /* decrypted plain-text */
#endif /* GCM-SIV */
/**----------------------------------------------------------------------------
Main functions for CCM-AES block ciphering
-----------------------------------------------------------------------------*/
#if CCM
void AES_CCM_encrypt( const uint8_t* key, /* encryption key */
const uint8_t* iVec, /* initialization vector/ nonce */
const uint8_t* pText, /* plain text */
const size_T pTextLen, /* length of input plain text */
const uint8_t* aData, /* added authentication data */
const size_T aDataLen, /* size of authentication data */
uint8_t* cText, /* cipher-text buffer */
uint8_t* auTag ); /* message authentication tag */
char AES_CCM_decrypt( const uint8_t* key, /* decryption key */
const uint8_t* iVec, /* initialization vector/ nonce */
const uint8_t* cText, /* cipher text */
const size_T cTextLen, /* length of input cipher-text */
const uint8_t* aData, /* added authentication data */
const size_T aDataLen, /* size of authentication data */
const uint8_t* auTag, /* authentication tag */
const uint8_t tagSize, /* size of tag (if any) */
uint8_t* pText ); /* decrypted plain-text */
#endif /* CCM */
/**----------------------------------------------------------------------------
Main functions for OCB-AES block ciphering
-----------------------------------------------------------------------------*/
#if OCB
void AES_OCB_encrypt( const uint8_t* key, /* encryption key */
const uint8_t* nonce, /* 96-bit initialization vector */
const uint8_t* pText, /* plain text */
const size_T pTextLen, /* length of input plain text */
const uint8_t* aData, /* added authentication data */
const size_T aDataLen, /* size of authentication data */
uint8_t* cText, /* cipher-text buffer */
uint8_t* auTag ); /* message authentication tag */
char AES_OCB_decrypt( const uint8_t* key, /* decryption key */
const uint8_t* nonce, /* 96-bit initialization vector */
const uint8_t* cText, /* cipher text */
const size_T cTextLen, /* length of input cipher-text */
const uint8_t* aData, /* added authentication data */
const size_T aDataLen, /* size of authentication data */
const uint8_t* auTag, /* authentication tag */
const uint8_t tagSize, /* size of tag (if any) */
uint8_t* pText ); /* decrypted plain-text */
#endif /* OCB */
/**----------------------------------------------------------------------------
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, /* initialization vector */
const size_T nonceLen, /* size of provided nonce */
const uint8_t* pText, /* plain text */
const size_T pTextLen, /* length of input plain text */
#if !EAXP
const uint8_t* aData, /* added authentication data */
const size_T aDataLen, /* size of authentication data */
#endif
uint8_t* cText, /* cipher-text buffer */
uint8_t* auTag ); /* message authentication tag */
char AES_EAX_decrypt( const uint8_t* key, /* decryption key */
const uint8_t* nonce, /* initialization vector */
const size_T nonceLen, /* size of provided nonce */
const uint8_t* cText, /* cipher text */
const size_T cTextLen, /* length of input cipher-text */
#if !EAXP
const uint8_t* aData, /* added authentication data */
const size_T aDataLen, /* size of authentication data */
const uint8_t* auTag, /* authentication tag */
const uint8_t tagSize, /* size of tag (if any) */
#endif
uint8_t* pText ); /* decrypted plain-text */
#endif /* EAX */
/**----------------------------------------------------------------------------
Main functions for AES key-wrapping; more info at the bottom of this page.
-----------------------------------------------------------------------------*/
#if KWA
void AES_KEY_wrap( const uint8_t* kek, /* key encryption key */
const uint8_t* secret, /* input secret to be wrapped */
const size_T secretLen, /* size of input */
uint8_t* wrapped ); /* key-wrapped output */
char AES_KEY_unwrap( const uint8_t* kek, /* key encryption key */
const uint8_t* wrapped, /* key-wrapped secret */
const size_T wrapLen, /* size of input (secretLen +8) */
uint8_t* secret ); /* buffer for unwrapped key */
#endif /* KWA */
#ifdef __cplusplus
}
#endif
/**----------------------------------------------------------------------------
These constants should be defined here for external references:
-----------------------------------------------------------------------------*/
#define ENCRYPTION_FAILURE 0x1E
#define DECRYPTION_FAILURE 0x1D
#define AUTHENTICATION_FAILURE 0x1A
#define ENDED_IN_SUCCESS 0x00
#if (AES___ == 256) || (AES___ == 192)
#define AES_KEY_LENGTH (AES___/8)
#else
#define AES_KEY_LENGTH 16
#endif
#endif /* header guard */
/**--------------------------------------------------------------------------**\
=< Notes and remarks about the above-defined macros >=
------------------------------------------------------------------------------
* Some AES modes just use the 'encryption' part of the Rijndael algorithm. So if
you are NOT using the decryption functions of ECB/CBC/KWA/XEX modes, you can
safely disable DECRYPTION macro and save a few kilobytes in compiled code.
* In EBC/CBC/XEX modes, the size of input must be a multiple of block-size.
Otherwise it needs to be padded. The simplest (default) padding mode is to
fill the rest of block by zeros. Supported standard padding methods are
PKCS#7 and ISO/IEC 7816-4, which can be enabled by AES_PADDING macro.
* In many texts, you may see that the words 'nonce' and 'initialization vector'
are used interchangeably. But they have a subtle difference. Typically nonce
is a part of the I.V, which itself can either be a full block or a partial
one. In CBC/CFB/OFB modes, the provided I.V must be a full block. In pure
CTR mode (CTRNA) you can either provide a 96-bit I.V and let the count start
at INIT_CTR_VALUE, or use a full block I.V. Anyhow, according to RFC-3686,
the counter value must start at 1.
* In AEAD modes, the size of nonce and tag might be a parameter of the algorithm
such that changing them affect the results. In CCM, the nonce/I.V size may
vary from 8 to 13 bytes. Also the tag size is an EVEN number between 4..16.
In OCB, only the tag size is a parameter between 0..16 bytes. The GCM mode
is independent from both. Nonetheless, the 'calculated' tag size is always
16 bytes which can later be truncated to the desired value. So in encryption
functions, the provided authTag buffer must be at least 16 bytes long.
* The EAX mode supports arbitrary size for nonce. The IEEE-1703 standard defines
EAX' which is a modified version of EAX, combining 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.
* In SIV mode, multiple separate units of authentication headers can be provided
for nonce synthesis. Here we assume that only one unit of AAD is sufficient,
which is practically true.
* The key wrapping mode is also denoted by KW. In this mode, according to RFC-
3394, the input secret-to-be-wrapped is divided into 64-bit blocks. Number
of blocks is at least 2, and it is assumed that no padding is required. The
wrapped output has an additional block, i.e. outputSize = secretSize + 8.
*/

8013
testvectors/XTSGenAES128.rsp Normal file

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

125
testvectors/testvec.c Normal file
View File

@@ -0,0 +1,125 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../micro_aes.h"
#define TESTFILEPATH "XTSGenAES128.rsp"
static void str2bytes(const char* str, uint8_t* bytes)
#define char2num(c) (c > '9' ? (c & 7) + 9 : c & 0xF)
{
size_t i, j;
for (i = 0, j = ~0; str[i]; ++i)
{
if (str[i] < '0' || str[i] > 'f') continue;
if (j++ & 1) bytes[j / 2] = char2num(str[i]) << 4;
else bytes[j / 2] |= char2num(str[i]);
}
}
static void bytes2str(const uint8_t* bytes, char* str, size_t len)
#define num2char(x) ((x) > 9 ? 'a' - 10 + (x) : '0' + (x))
{
size_t i, j;
for (i = 0, j = 0; i < len; ++i)
{
str[j++] = num2char(bytes[i] >> 4);
str[j++] = num2char(bytes[i] & 15);
}
str[j] = 0;
}
static int ciphertest(uint8_t* key, uint8_t* iv, uint8_t* p, uint8_t* c, uint8_t n, char* r)
{
char sk[70], si[40], sp[70], sc[70], msg[30];
int false_negative = (n == 17 && (p[16] & 0x1F) == 0 && (c[16] & 0x1F) == 0);
uint8_t tmp[32], t = 0;
sprintf(msg, "%s", "success");
AES_XTS_encrypt(key, iv, p, n, tmp);
if (memcmp(c, tmp, n) && !false_negative)
{
sprintf(msg, "%s", "encrypt failure");
t = 1;
}
memset(tmp, 0xcc , sizeof tmp);
AES_XTS_decrypt(key, iv, c, n, tmp);
if (memcmp(p, tmp, n) && !false_negative)
{
sprintf(msg, "%sdecrypt failure", t ? "encrypt & " : "");
t |= 2;
}
bytes2str(key, sk, 32);
bytes2str(iv, si, 16);
bytes2str(p, sp, n);
bytes2str(c, sc, n);
sprintf(r, "%s\nk: %s\ni: %s\np: %s\nc: %s", msg, sk, si, sp, sc);
return t;
}
int main()
{
int n = 0, m = 0, pass = 0, df = 0, ef = 0;
char buffer[256], *value;
uint8_t key[32], iv[16], p[32], c[32], s = 0;
FILE *fp, *fs, *ferr;
fp = fopen(TESTFILEPATH, "r");
fs = fopen("passed.log", "w");
ferr = fopen("failed.log", "w");
if (fp == NULL)
{
printf("File not found: %s\n", TESTFILEPATH);
return 1;
}
if (!fs || !ferr) return 1;
while (fgets(buffer, sizeof buffer, fp) != NULL)
{
buffer[strcspn(buffer, "\n")] = 0;
if (strlen(buffer) < 4 || !strcspn(buffer, "=")) continue;
if (strcspn(buffer, "Key =") == 0)
{
value = strrchr(buffer, ' ');
str2bytes(value + 1, key);
}
else if (strcspn(buffer, "i =") == 0)
{
value = strrchr(buffer, ' ');
str2bytes(value + 1, iv);
}
else if (buffer[1] == 'T' && (buffer[0] == 'P' || buffer[0] == 'C'))
{
value = strrchr(buffer, ' '); ++n;
s = strlen(value + 1) / 2;
str2bytes(value + 1, buffer[0] == 'P' ? p : c);
}
if (n == m + 2)
{
char report[640];
m = ciphertest(key, iv, p, c, s, report);
if (m == 0)
{
fprintf(fs, "%s\n", report);
++pass;
}
else
{
fprintf(ferr, "%s\n", report); /* test has failed :(( */
if (m & 1) ++ef;
if (m & 2) ++df;
}
m = n;
}
}
printf ("test cases: %d, successful: %d, failed encrypt: %d, failed decrypt: %d\n",
pass + ef + df, pass, ef, df);
fclose(fp); fclose(fs); fclose(ferr);
if (ef + df == 0)
{
remove("passed.log"); remove("failed.log");
}
return 0;
}

46
testvectors/testvecs.cbp Normal file
View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="testvecs" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin/Debug/testvecs" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Debug/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-pedantic" />
<Add option="-ansi" />
<Add option="-g" />
</Compiler>
</Target>
<Target title="Release">
<Option output="bin/Release/testvecs" prefix_auto="1" extension_auto="1" />
<Option object_output="obj/Release/" />
<Option type="1" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O2" />
<Add option="-pedantic" />
<Add option="-ansi" />
</Compiler>
<Linker>
<Add option="-s" />
</Linker>
</Target>
</Build>
<Unit filename="../micro_aes.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="../micro_aes.h" />
<Unit filename="testvec.c">
<Option compilerVar="CC" />
</Unit>
<Extensions>
<lib_finder disable_auto="1" />
</Extensions>
</Project>
</CodeBlocks_project_file>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_layout_file>
<FileVersion major="1" minor="0" />
<ActiveTarget name="Debug" />
<File name="testvec.c" open="0" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="3108" topLine="93" />
</Cursor>
</File>
<File name="..\micro_aes.c" open="0" top="0" tabpos="0" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0">
<Cursor>
<Cursor1 position="13829" topLine="327" />
</Cursor>
</File>
</CodeBlocks_layout_file>

88
vc.vcxproj Normal file
View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{B2A73B4A-401B-4D6D-9386-23D2CAE90D08}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>vcaes</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<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>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.c" />
<ClCompile Include="micro_aes.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="micro_aes.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>