Git Product home page Git Product logo

tiny-aes-c's People

Contributors

acortelyou avatar bitdust avatar bricke avatar dklayer avatar dmitrystu avatar jsiverskog avatar k6dsp avatar kokke avatar lucifurtun avatar mb300sd avatar namreeb avatar nickaknudson avatar pjunni avatar raptorfactor avatar rkeene avatar stargate01 avatar torfinnberset avatar youw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tiny-aes-c's Issues

Memory access violation

In KeyExpansion, the line which initialize the first RoundKey should be
memcpy(RoundKey, Key, AES_KEYLEN);

Using AES_keyExpSize as the length of 'Key' causes memory issues.

I also think it is best that AES_init_ctx should have arrays initialization:
memset(ctx->RoundKey, 0, AES_keyExpSize); #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) memset(ctx->Iv, 0, AES_BLOCKLEN); #endif

End up looking like this:
void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key) { memset(ctx->RoundKey, 0, AES_keyExpSize); #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) memset(ctx->Iv, 0, AES_BLOCKLEN); #endif KeyExpansion(ctx->RoundKey, key); }

Cross platform use

Hey guys!

Wondering if you support multi platform use for ex:
Encrypt on armv7 (32 bit bi-endian) and decrypt on x86_64 (64 bit little endian).

Cheers,
Lucas.

Reverse state indicies

If you reverse the indices used in the state array (state[i,j] becomes state[j,i]), in/out values become a direct copy of the state array in memory. I made some modifications so it does in place encryption/decryption without creating separate in/out/state copies.

Link to modified file:
http://pastebin.com/nYzYvvNp

openssl compat

Hi,
is possible decrypt openssl using openssl cmdline tool ?

i.e.,
generate a file encrypted with aes-128-c ebc and use openssl to check or decrypt ?

thanks!

CBC Mode Final Padded Block Bug

Just noted that the CBC encrypt code does NOT apply the IV to the final block when the length of the plain text is not an exact multilple of KEYLEN. In this instance the if(remainders>0){ } code after the FOR loop is executed and in that section the IV is NOT applied.

Iv is used uninitialized if iv parameter is 0 in AES_CBC_encrypt_buffer().

Hi!
It looks like Iv can be used uninitialized in AES_CBC_encrypt_buffer() if iv parameter is 0.

AES_CBC_encrypt_buffer(input, output, size, key, 0):
{
...
  if (iv != 0) // iv is 0, so next line is not executed
  {
    Iv = iv;
  }

  for (i = 0; i < length; i += BLOCKLEN)
  {
    XorWithIv(input);  // this function uses Iv, which is not initialized!

The same thing with AES_CBC_decrypt_buffer().

I suggest adding default value for initial vector:

#if defined(CBC) && CBC
  // Initial Vector used only for CBC mode
  static const uint8_t * Iv;
  static const uint8_t defaultIv[BLOCKLEN] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
#endif

and replace

  if (iv != 0) // iv is 0, so next line is not executed
  {
    Iv = iv;
  }

with

  Iv = iv ? iv : defaultIv;

in AES_CBC_encrypt_buffer() and AES_CBC_decrypt_buffer()

Add examples.

I would like some example programs that can use this to encrypt or decrypt or both files on the filesystem as well (like opening a file, reading the data, encrypting/decrypting it, writing the data, closing the file). This is because I might be thinking of Making an exe compressor or something with this and (maybe zlib) if I can figure out memory zlib compressing as well.

Thread safety

The code uses global variables for key/iv this is horribly thread unsafe! I know this is supposed to be mcu implementation but yet passing arguments around should not be that big of an issue. At least the there could be an -DTHREADSAFE option to compile a thread safe version of this code.

Redundant BlockCopy() call at start of AES128_CBC_encrypt_buffer()

Summary

At the beginning of the CBC encrypt/decrypt functions the contents of the input buffer is copied to the output buffer, this is also done for ECB mode. The initial copy in ECB mode is necessary, but seems to be redundant in the CBC functions. The exact same copy is later made in the for loop iterating through the AES blocks.

A visual inspection of AES128_CBC_encrypt_buffer() and AES128_CBC_decrypt_buffer() should confirm the issue.

Testing

The tests pass with the redundant copy removed.

Fix

Remove redundant call to BlockCopy() in AES128_CBC_encrypt_buffer() and AES128_CBC_decrypt_buffer().

Existing Fixes

I had a hunt through the pull requests and found the following un-merged requests that address this issue:

  • #18 Removes redundant copy, as well as other changes.

  • #23 Lots of fixes to CBC implementation including this redundant block copy.

Conclusion

This is a simple fix that can shave off a few redundant CPU cycles, unless the compiler is already optimising it out for you ๐Ÿ˜„

I am happy to prepare a pull request addressing this issue only, if there's interest.

null pointer is used

Hi, kokke.

I forked your code and used in my project.
I met a problem. Let me show you code.

In this functon:
void AES128_CBC_encrypt_buffer(
uint8_t* output, uint8_t* input,
uint32_t length, const uint8_t* key, const uint8_t* iv)
If I pass parameter "iv" and "iv" equals 0, then:
if(iv != 0) //cause iv equals 0, then static var Iv isn't assimented, Iv's default value maybe 0
{
Iv = (uint8_t*)iv;
}

and then:
static void XorWithIv(uint8_t* buf)
{
uint8_t i;
for(i = 0; i < KEYLEN; ++i)
{
//casue Iv isn't initialized, this line probably generates segmentfalut
buf[i] ^= Iv[i];
}
}

encrypt different between openssl and this

I use openssl encrypt a string, the result is "8oaoH1JOBl3+QgRoEc5l0pYF5aMN1+p7AT/xAgUIST8="

echo -n "1234567890abcdef" | openssl enc -K 2b7e151628aed2a6abf7158809cf4f3c -iv 000102030405060708090a0b0c0d0e0f -aes-128-cbc -base64

but when use functuon AES128_CBC_encrypt_buffer, the result(after base64) is

"8oaoH1JOBl3+QgRoEc5l0g=="

I has set the key and IV as same sa openssl

Why are there have two differnet result? Thank you!
How can i enable pading in AES128_CBC_encrypt_buffer

the library is not thread-safe

We are using the lib inside a mulitply-threads context and found it is not thread-safe. There are global variables are using to optimized some internal parameters delivery.
For instance:
static state_t* state;
static uint8_t RoundKey[keyExpSize];
static const uint8_t* Key;
After remove them, lib are working propertly under mulitply-threads.

unnecessary change of input?

I see in AES_CBC_encrypt_buffer code:
XorWithIv(input); memcpy(output, input, BLOCKLEN);
I was expecting something like:
memcpy(output, input, BLOCKLEN); XorWithIv(output);

Decryption problem

Hi

When I use the tiny-AES128 for both encryption and decryption it is working fine. But when I try to decrypt the same with any other program I get a partial decryption. I am not very good at C. So I am not sure if I am doing something wrong or if there is a bug. Below is are the details.

Key & IV: same as in text.c
#uint8_t encrypt_key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };
#uint8_t iv[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };

Encrypted Hex: AE8384D8E0AF32B801DA80E5CD05D7E8E916E853CAB551AB91966F540694A4D9

Plain Text: AAA000000001#starnet000000000000

When I decrypting the same using pyaes (python) and online (http://aes.online-domain-tools.com/) I the following decrypted message.

AAA000000001#sta???ิš?9???8??

The message is garbled after sta. Please let me know what is wrong.

Thanks & Regards
Vijay

memcpy rather than loop?

Hey,

Great bit of code, should save me from using openssl (hopefully)! Just curious, on this section what made you use a loop rather than just memcpy(output,input,KEYLEN) ?:

static void BlockCopy(uint8_t* output, uint8_t* input) { uint8_t i; for (i=0;i<KEYLEN;++i) { output[i] = input[i]; } }

Of course memcpy itself is a call and then another loop but it might on some computers/compilers it might be more optimised then byte by byte copying

Add GCM block cipher mode

Both modes work indeed as stated by the NIST. Adding a counter mode would be awesome since CBC can stil be used in BEAST and ECB is vulnerable to plaintext attacks.

Encrypt string with dash will decrypt badly

I think it's the dashes.

uint8_t input[17] = "2014-02-20 13:27";
// strftime((char*)input, sizeof(input), "%Y-%m-%d %H %M", &tstruct);
std::cout << input<<"\n";
uint8_t output[ sizeof(input) +16];
AES128_ECB_encrypt(input, key, output);
size_t size = sizeof(output);
uint8_t decrypted[17];
AES128_ECB_decrypt(output, key, decrypted);
std::cout << decrypted<< "\n";

Will output:
image

Could you provide more usage examples ?

Hi,
I couldn't find another way to contact you so I'm using this.
Could you be kind enough to share some usage examples ?
I've seen the tests so I've managed to understand most of it, but I have problems trying to use a key longer then 16 bits.
Thank you

Not working on Arduino Uno, AVR not even booting

Hi, thanks for the great code. It looks really clean and elegant implementation, and I love the fact you have CBC, but sadly I can't get it to work.

I placed the files as-is in the libraries directory and just by including "aes.h" the program compiles but:

  1. The ram usage spikes by 764 bytes. If you get 200 bytes on a 32 bit processor how can I get 3x that in an 8 bit one?
  2. If I upload the code just with the include, the Arduino will fail to start, like it just hangs.
  3. If I just comment the include line, the program uploads and the AVR starts working again.

I noticed you said you have tested this in AVR. Can you pls. post instructions on how you got it working? Perhaps I am doing something wrong.

TIA,
Alex

Eliminate Rcon array to save space

The Rcon array currently takes 255 bytes of ROM, but only its first 11 elements are accessed, since there are only 10 rounds. Therefore the remaining 244 elements should be removed. The first element can also be removed when the array index is adjusted by -1.

The whole array can be replaced by starting a local variable uint8_t rcon = 0x01 and applying xtime after each round, which is a little slower but eliminates the need for fixed constants.

Different input

Premise: I'm not confident with C.
Is there a way to use this method:

void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);

by passing (char* output, char* input, uint32_t length, const char* key, const char* iv) ?

input buffer pointers can be const

Things like this:

void AES128_ECB_encrypt(uint8_t* input, const uint8_t* key, uint8_t *output);
void AES128_ECB_decrypt(uint8_t* input, const uint8_t* key, uint8_t *output);

Can be changed to:

void AES128_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t *output);
void AES128_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output);

Linker error

In the test.c file, it does #include "aes.h" as the library. This is incorrect and will lead to linker errors. Please replace that with #include "aes.c" instead. Then it works fine at compilation. I'm only writing this because it may lead to confusion. Although I would like to know why the header file does not #include "aes.c". Seems a bit odd. Besides that, great library, really nice performance.

iv variable

Am I supposed to add logic to generate iv values or is this built in somewhere?

Have you used this with AVR?

I'm facing problem on encryption. It generating values here then 255. So how to manage that? Can you please share implementation of this code on AVR?

The CTR test does not test decryption

Hi,

In the CTR test (test.c), the test_xcrypt_ctr() function is invoked twice, once for encryption, once for decryption. However, the only difference between both invocations is the printed string, not the transformed data. Both invocations transform the in buffer and verify that the result is equal to the out buffer. Instead, the second invocation should transform (decrypt) the out buffer, and verify that the result is equal to the in buffer.

The change in code to achieve that is trivial, and fortunately, that test too passes on my old 16-bit DSP. :-)

Thanks again for sharing.

Best regards,

Alain Mosnier

No Input Output Parameters

I want to use these files in the Android NDK but unable to convert the string passed from java end to convert in the uInt_8 array and return an output string as being dumb in C.
Please, can you make the methods so that the return the encrypted string as output string and accept an input as plain text so that I can implement it easily?
Also, I want to provide the iv and key in the string format.

So please take plainText = "plaintext", iv="iv_key213123", key="key_qwerwqer", and return the output as
cypherText.
Hope it makes sense?

ECB or CBC

The readme says,

GCC size output when only ECB mode is ...

but the command is
arm-none-eabi-gcc -Os -c aes.c -DCBC=0

Is that a typo?

CBC Encryption/Decryption Bug when input Data length < 16

The loop that starts for(i = 0; i < length; i+=KEYLEN) will always executes once provided that the length is non zero. When the input data length is < KEYLEN and >0 then BOTH this loop and the block following it that handles the final partial block ("remainders") get executed. This is clearly incorrect.

I feel that logically the for loop should be looping through whole blocks and the loop count should not be a pointer! so something like for(u8 b = 0;b<NumCompleteBlocks;NumCompleteBlocks++)
u8 = uint_8

One then must then either pad out input data BEFORE the for loop if length is <KEYLEN, or add a check in the remainders block to ensure the IV is applied if NumCompleteBlocks=0 but not otherwise.

Apologies but I am new to GIT and not sure of the correct protocols!
Thanks

Compile

I try to compile the test.c file and I obtain the following errors:

"_AES_CBC_decrypt_buffer", referenced from:
      _test_decrypt_cbc in test-602b3e.o
  "_AES_CBC_encrypt_buffer", referenced from:
      _test_encrypt_cbc in test-602b3e.o
  "_AES_ECB_decrypt", referenced from:
      _test_decrypt_ecb in test-602b3e.o
  "_AES_ECB_encrypt", referenced from:
      _test_encrypt_ecb in test-602b3e.o
      _test_encrypt_ecb_verbose in test-602b3e.o

Does someone know how to fix this? Thanks in advance.

Multiblock CBC decryption failed

Current CBC decryption implementation causes damage of Iv data when you reload your input buffer. So any next call of AES128_CBC_decrypt_buffer(out, in, size, NULL, NULL) causes invalid result. To solve it add new buffer for Iv data which filled in decrypt function before exit.

Missing array element

a
b

Also only the first some of these constants are actually used โ€“ up to rcon[10] for AES-128 (as 11 round keys are needed).

rcon[0] is not used in AES algorithm.

The Rijndael variants with larger block sizes use more of these constants, up to rcon[29] for Rijndael with 128-bit keys and 256 bit blocks (needs 15 round keys of each 256 bit, which means 30 full rounds of key expansion, which means 29 calls to the key schedule core using the round constants).

(C) WiKi

Compiling the program

hi,
I am compiling this program in windows machine.Please let me know to how to compile this program
gcc -o aes aes.c gives undefined ref errors

Cannot handle buffered input

I am using your code for an embedded application (thank you very much BTW) that decrypts packetized ciphertext on the fly. The cipher text arrives on my embedded box in a circular buffer. Your implementation relies on the previous input persisting across calls to be reused as the next IV. A simple fix is to declare Iv as a byte array and then replace the pointer assignment with a memcpy.

for (i = 0; i < length; i += KEYLEN)
{
	BlockCopy(output, input);
	state = (state_t*)output;
	InvCipher();
	XorWithIv(output);
#ifdef STATIC_INPUT_ONLY
	Iv = input;
#else 
        memcpy(Iv,input,sizeof(Iv));
#endif
	input += KEYLEN;
	output += KEYLEN;
}

Inaccurate comment for AES_CTR_xcrypt_buffer()?

Hi,

Correct me if I am wrong, but I believe the comment "buffer size MUST be multiple of AES_BLOCKLEN" is inaccurate for AES_CTR_xcrypt_buffer() (in aes.h).

What if it's not? I believe Wikipedia's description of the case:

  • The last partial block of plaintext is XORed with the first few bytes of the last keystream block, producing a final ciphertext block that is the same size as the final partial plaintext block.

would apply to this implementation.

Requiring padding for CTR would also, in my interpretation, fail to fulfill NIST SP 800-38A, that specifies padding for ECB, CBC, and CFB modes only.

In other words, I believe this implementation is better than advertised, and the comment should be updated to reflect that. :-)

Thanks for putting this implementation in the public domain.

Best regards,

Alain Mosnier

aes128-cbc encrypt result differ from openssl command line?

hi. I am a beginner of encrypt algorithm.
i want to compare the 'tiny-aes128-c' encrypt with openssl. but the encrypt results are different.

Here is my practice:

the tiny-AES128-C code:

#include "aes.h"
#include <stdio.h>

void phex(uint8_t *str, int len)
{
    int i;
    for(i=0; i<len; ++i){
        printf("%.2x ", str[i]);
    }
    printf("\n");
}

int main()
{
    const uint8_t key[16] = {0x12, 0x23};
    const uint8_t iv[16] =  {0xF1, 0x23};
    uint8_t in[16] = "1234567890abc";
    uint8_t out[16];

    AES128_CBC_encrypt_buffer(out, in, sizeof(in), key, iv);
    phex(out, sizeof(out));

    return 0;
}

the tiny-AES128-C encrypt result is:

fd a3 86 e1 51 3f 9f 4a 8b 21 84 ee b4 bd 79 3e 

openssl commnad line encrypt

$echo "1234567890abc" > plain.txt
$openssl enc -aes-128-cbc -in plain.txt  -out encrypt.txt  -K 1223 -iv f123 -p
$xxd encrypt.txt

default
$xxd plain.txt
default

$xxd encrypt.txt
default

Result Compare

tiny-aes128-c:

fd a3 86 e1 51 3f 9f 4a 8b 21 84 ee b4 bd 79 3e

openssl:

c5 af 18 cb dd ee 99 23 03 74 6a 21 9b b6 3f 99

why is difference?

Thank you!

License?

I started to add CBC mode to tiny-AES, but I realized I don't know what open source license the base code is under. Could you let us know in the readme?

Speed enhancements

Hi,

I was very glad to find this library but I noticed some little things in the source code that can slow down the encryption/decryption process.

All the multiplications are by 4 but it's a lot quicker to shift the number two times to the left when you don't have an hardware multiplier.

For example, this code :

for(i = 0; i < Nk; ++i)
{
RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
}

could be changed to :

uint32_t i4;
for(i = 0; i < Nk; ++i)
{
i4 = i<<2;
RoundKey[(i4) + 0] = Key[(i4) + 0];
RoundKey[(i4) + 1] = Key[(i4) + 1];
RoundKey[(i4) + 2] = Key[(i4) + 2];
RoundKey[(i4) + 3] = Key[(i4) + 3];
}

Or in this case, you can also increment i by 4 in your for loop.

How to handle short string / files

When encrypting the string, if the string is less than a multiple of 16, pad the string with hex zeros to make the length become an exact multiple of 16. In the final byte of the padded value, indicate as a character (1-x0f), the actual length of the data that is valid within the padded block.

If the string is exactly a multiple of 16 bytes, add a padded block of hex zeros. The final byte will contain hex zero, which states that none of the final block is used.

When decoding, examine the last block of 16 bytes. That final byte indicates how many characters of this last block are valid.

I use this technique elsewhere, When I get a chance I will post my solution. My solution works with ecb or with cypher block chaining mode.

Use memcmp instead of strncmp in test.c

The function strncmp() will stop comparing when it encounters a NULL character in either string. For example, given the following data, strncmp() would report 0 (match), whereas memcmp() would report non-zero (mismatch).

uint8_t buf1[] = {3, 0, 1, 2};
uint8_t buf2[] = {3, 0, 1, 3};

false_result = strncmp((char *)buf1, (char *)buf2, 4);
true_result = memcmp(buf1, buf2, 4);

Using memcmp() for comparing byte sequences which are not null-terminated strings will fix this problem.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.