UNIXworkcode

/* * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE * Version 2, December 2004 * * Copyright (C) 2017 Olaf Wintermann <olaf.wintermann@gmail.com> * * Everyone is permitted to copy and distribute verbatim or modified * copies of this license document, and changing it is allowed as long * as the name is changed. * * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION * * 0. You just DO WHAT THE FUCK YOU WANT TO. */ #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]; // encryption initialization vector // open /dev/urandom and read 16 bytes 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; } // create cryptor 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; // encrypt 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]; // open /dev/urandom and init key with 32 random bytes 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; } // encrypt text crypt_msg cmsg; if(aes_encrypt(text, textlen, key, 32, &cmsg)) { fprintf(stderr, "aes_encrypt failed\n"); } // decrypt cmsg 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); }