#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <CommonCrypto/CommonCrypto.h>
#include <CommonCrypto/CommonDigest.h>
typedef struct {
void *iv;
void *data;
size_t len;
} crypt_msg;
typedef struct {
void *buf;
size_t len;
} plain_msg;
int aes_encrypt(void *msg, size_t len, void *key, size_t keylen, crypt_msg *ret) {
char iv[16];
int devr = open("/dev/urandom", O_RDONLY);
if(devr == -1) {
return -1;
}
ssize_t rr = read(devr, iv, 16);
close(devr);
if(rr != 16) {
return -1;
}
CCCryptorRef cryptor;
if(CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding, key, 32, iv, &cryptor) != kCCSuccess) {
return -1;
}
size_t outlen = len - (len % 16) + 32;
char *outbuf = malloc(outlen);
memcpy(outbuf, iv, 16);
char *data = outbuf + 16;
size_t datalen = outlen - 16;
crypt_msg c;
c.iv = outbuf;
c.data = data;
c.len = 0;
size_t moved;
CCCryptorStatus status;
status = CCCryptorUpdate(cryptor, msg,
len, data, datalen,
&moved);
if(status != kCCSuccess) {
free(outbuf);
return -1;
}
data += moved;
datalen -= moved;
c.len += moved;
status = CCCryptorFinal(cryptor, data, datalen, &moved);
if(status != kCCSuccess) {
free(outbuf);
return -1;
}
c.len += moved;
*ret = c;
return 0;
}
int aes_decrypt(crypt_msg cmsg, void *key, size_t keylen, plain_msg *ret) {
CCCryptorRef cryptor;
if(CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding, key, 32, cmsg.iv, &cryptor) != kCCSuccess) {
return -1;
}
char *outbuf = malloc(cmsg.len);
size_t outavail = cmsg.len;
char *buf = outbuf;
size_t len = 0;
size_t moved;
CCCryptorStatus status;
char *data = cmsg.data;
size_t datalen = cmsg.len;
status = CCCryptorUpdate(cryptor, cmsg.data, cmsg.len, outbuf, outavail, &moved);
if(status != kCCSuccess) {
free(outbuf);
return -1;
}
outavail -= moved;
buf += moved;
len += moved;
status = CCCryptorFinal(cryptor, buf, outavail, &moved);
if(status != kCCSuccess) {
free(outbuf);
return -1;
}
len += moved;
plain_msg msg;
msg.buf = outbuf;
msg.len = len;
*ret = msg;
return 0;
}
int main(int argc, char** argv) {
char *text = "Hello World!";
size_t textlen = strlen(text);
char key[32];
int devr = open("/dev/urandom", O_RDONLY);
if(devr == -1) {
return -1;
}
ssize_t rr = read(devr, key, 32);
close(devr);
if(rr != 32) {
return -1;
}
crypt_msg cmsg;
if(aes_encrypt(text, textlen, key, 32, &cmsg)) {
fprintf(stderr, "aes_encrypt failed\n");
}
plain_msg pmsg;
if(aes_decrypt(cmsg, key, 32, &pmsg)) {
fprintf(stderr, "aes_decrypt failed\n");
}
printf("decrypted text: %.*s\n", (int)pmsg.len, pmsg.buf);
return (EXIT_SUCCESS);
}