5

I'm using CommonCrypto for encryption in Objective-C (AES256) and I'd like to provide an IV (initialization vector) for a more secure encryption. I'm currently doing this:

const void* iv = malloc(kCCBlockSizeAES128);
// EDIT:
//if (!iv) {
//    iv = NULL;
//}

and then I create the cryptor object:

CCCryptorRef cryptor;
CCCryptorStatus cryptStatus = CCCryptorCreate(operation, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                                  keyPtr, kCCKeySizeAES256,
                                                  iv,
                                                  &cryptor);

The problem is that encryption this way seems to fail (sad face...). I mean: it encrypts with no apparent problem, but it decrypts data different than the original. I though this would work because when you malloc() memory, it is not written all to zeros, it is random. I also tried writing random values myself but my C background is failing really hard. If there is a function (like bzero) that writes random bytes please tell me.

I also tried doing something like this:

char* iv = malloc(kCCBlockSizeAES128);
int i;
srand((unsigned int)time(NULL));
for (i = 0; i < kCCBlockSizeAES128; i++) {
    iv[i] = (char)rand()%256;
}

Ohh, by the way, I realise this must be a very nooby question :)

In the end all I want is something like const void* iv = malloc(kCCBlockSizeAES128) that after some operations I am sure it's data is completely random. Any ideas on that?

PS: I only provided the crypto/Objective-C background so you know what I need this for. I think that won't influence a thing. kCCBlockSizeAES128 = 16 (90% sure :)

EDIT:

Allright! After some deugging I'm happy to announce that the problem I was having with the encryption & decryption was due to a bug in another part of my program I have now solved. So all I need to figure now is how to fill the iv with random bytes. Some options:

  • Use malloc(), which returns junk, not random bytes -> potentially insecure (?)
  • Use arc4random_buf(), which is exactly what I want except it only works 10.7+ and my mac is 10.6.6 (plus I want to support 10.6)
  • Something else I haven't considered...? <-- help here!

EDIT 2:

Allright! After filling the iv with some test data (all zeros, all ones, etc) and some more deugging I'm NOT happy to announce that ccrypto doesn't seem to be working in some conditions. I'll explain how:

Whenever I feed the crypto a zeroed iv or NULL (same thing for crypto) it works. For example, this works well when encrypting and decrypting:

uint8_t iv[kCCBlockSizeAES128];
int i;
for (i = 0; i < kCCBlockSizeAES128; i++) {
    iv[i] = 0x0; // I know this is the same as doing: memset((void *)iv, 0x0, (size_t)sizeof(iv));
}

CCCryptorRef cryptor;
CCCryptorStatus cryptStatus = CCCryptorCreate(operation, kCCAlgorithmAES128,
                                              kCCOptionPKCS7Padding,
                                              (const void *)keyPtr, kCCKeySizeAES256,
                                              iv,
                                              &cryptor);

BUT when I feed him a iv in which at least ONE of it's bytes is NOT zero, encryption/decryption do not provide errors but decrypting doesn't yield the original data. For example, this...

uint8_t iv[kCCBlockSizeAES128];
int i;
for (i = 0; i < kCCBlockSizeAES128; i++) {
    iv[i] = 0x1;
}

or for completely random data...

uint8_t iv[kCCBlockSizeAES128];
int i;
for (i = 0; i < kCCBlockSizeAES128; i++) {
    iv[i] = arc4random() % 256;
}

...won't work.

I do not understand this logic one single bit... Any ideas?

Alex
  • 5,009
  • 3
  • 39
  • 73
  • 6
    Comment: `if (!iv) { iv = NULL; }` makes no sens. – Mat Aug 07 '11 at 11:48
  • @Mat I did that because if you provide the crpypto with NULL, it will create an IV itself with all zeros always. When I can't create an IV I let crypto create a zeroed IV. Otherwise I want to have a random IV. – Alex Aug 07 '11 at 11:54
  • 1
    Your post is very vague: "seems to fail"? Make sure it is failing. Also that crypto function should work regardless of the contents of the IV - might not be secure, but will work. So your problem is probably elsewhere. Please describe in more detail _what_ is not working and how it's failing. (The statement inside the `if` block will only run if `!iv` is true, which only happens if `iv == null`...) – Mat Aug 07 '11 at 11:55
  • @Mat Well, I say it seems to fail because I encrypt a file with no problems, but when I decrypt it it's info is different than the original file. You're right, this is pretty vague. I'll continue debugging. If I find something I'll let you know. About if (!iv) {...}, I see what you mean now :) – Alex Aug 07 '11 at 12:06
  • @Mat I have updated my question, could you please check it again? – Alex Aug 07 '11 at 18:50
  • Are you using the same IV for decryption? – Mat Aug 07 '11 at 18:58
  • No, I'm not. I have tried giving crypto NULL (zeroed IV) on decryption and also a random IV using the methods above. None worked. Should I? If so, how? Am I supposed to save it with the file or something? – Alex Aug 07 '11 at 20:58
  • If you don't know whether you should be using the same IV or not, you've got to go back to studying your crypto algorithm and cipher mode of operation. You really _need_ to understand that to be able to implement encryption. – Mat Aug 07 '11 at 21:02
  • @Mat Wow, yes, of course. You're completely right. I hope I'm not missing anything else. I had no idea I had to use the same iv. Thank you very much for pointing that out. Now I just need to figure out the inner workings for the first 16 bytes being the IV. Thanks, I guess I know how to do it now :) – Alex Aug 07 '11 at 21:50

1 Answers1

11

You can use arc4random_buf to fill the buffer with random data:

#include <stdlib.h>
#include <stdint.h>

uint8_t iv[kCCBlockSizeAES128];
arc4random_buf(&iv, kCCBlockSizeAES128);

Also, the memory block returned by malloc (as with any uninitialised memory) is filled with garbage. You should not assume that it will be filled with anything, especially not cryptographically useful random numbers.

一二三
  • 21,059
  • 11
  • 65
  • 74
  • The compiler can't find the function `arc4random_buf`, even with the import statement. Is it arc4random_addrandom() or something like it? – Alex Aug 07 '11 at 12:21
  • Make sure you're compiling against the Mac OS X 10.7 or iOS 4.3 (or higher) SDK. – 一二三 Aug 07 '11 at 12:51
  • Well, I'm compiling with Mac OS 10.6... But will arc4random_addrandom() do? – Alex Aug 07 '11 at 12:58
  • No, `arc4random_addrandom` seeds the RNG, it doesn't produce any values. – 一二三 Aug 08 '11 at 06:06
  • 1
    this might be a dumb question, why are u passing &iv to arc4random_buf rather than just iv? I thought iv is already a pointer and we just need to put random data in where iv is pointing to... – Erben Mo Jan 17 '13 at 06:03
  • In this case, `iv` and `&iv` are equivalent. `&iv` is the address of the array, and `iv` decays into a pointer to the first element of the array when passed to a function (which are both the same). [The C Book](http://publications.gbdirect.co.uk/c_book/chapter5/arrays_and_address_of.html) has a more detailed explanation of this. – 一二三 Jan 21 '13 at 08:42
  • 1
    isn't &iv the address containing the value of the pointer? I think you should pass iv and not &iv – David 天宇 Wong Feb 24 '16 at 22:36