UNIXworkcode

1 /* 2 * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 3 * Version 2, December 2004 4 * 5 * Copyright (C) 2017 Olaf Wintermann <olaf.wintermann@gmail.com> 6 * 7 * Everyone is permitted to copy and distribute verbatim or modified 8 * copies of this license document, and changing it is allowed as long 9 * as the name is changed. 10 * 11 * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 12 * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 13 * 14 * 0. You just DO WHAT THE FUCK YOU WANT TO. 15 */ 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <unistd.h> 21 #include <fcntl.h> 22 23 #include <CommonCrypto/CommonCrypto.h> 24 #include <CommonCrypto/CommonDigest.h> 25 26 typedef struct { 27 void *iv; 28 void *data; 29 size_t len; 30 } crypt_msg; 31 32 typedef struct { 33 void *buf; 34 size_t len; 35 } plain_msg; 36 37 int aes_encrypt(void *msg, size_t len, void *key, size_t keylen, crypt_msg *ret) { 38 char iv[16]; // encryption initialization vector 39 40 // open /dev/urandom and read 16 bytes 41 int devr = open("/dev/urandom", O_RDONLY); 42 if(devr == -1) { 43 return -1; 44 } 45 ssize_t rr = read(devr, iv, 16); 46 close(devr); 47 if(rr != 16) { 48 return -1; 49 } 50 51 // create cryptor 52 CCCryptorRef cryptor; 53 if(CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding, key, 32, iv, &cryptor) != kCCSuccess) { 54 return -1; 55 } 56 57 size_t outlen = len - (len % 16) + 32; 58 char *outbuf = malloc(outlen); 59 60 memcpy(outbuf, iv, 16); 61 char *data = outbuf + 16; 62 size_t datalen = outlen - 16; 63 64 crypt_msg c; 65 c.iv = outbuf; 66 c.data = data; 67 c.len = 0; 68 69 // encrypt 70 size_t moved; 71 CCCryptorStatus status; 72 status = CCCryptorUpdate(cryptor, msg, 73 len, data, datalen, 74 &moved); 75 if(status != kCCSuccess) { 76 free(outbuf); 77 return -1; 78 } 79 80 data += moved; 81 datalen -= moved; 82 c.len += moved; 83 84 status = CCCryptorFinal(cryptor, data, datalen, &moved); 85 if(status != kCCSuccess) { 86 free(outbuf); 87 return -1; 88 } 89 90 c.len += moved; 91 *ret = c; 92 93 return 0; 94 } 95 96 int aes_decrypt(crypt_msg cmsg, void *key, size_t keylen, plain_msg *ret) { 97 CCCryptorRef cryptor; 98 if(CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding, key, 32, cmsg.iv, &cryptor) != kCCSuccess) { 99 return -1; 100 } 101 102 char *outbuf = malloc(cmsg.len); 103 size_t outavail = cmsg.len; 104 char *buf = outbuf; 105 106 size_t len = 0; 107 size_t moved; 108 CCCryptorStatus status; 109 110 char *data = cmsg.data; 111 size_t datalen = cmsg.len; 112 113 status = CCCryptorUpdate(cryptor, cmsg.data, cmsg.len, outbuf, outavail, &moved); 114 if(status != kCCSuccess) { 115 free(outbuf); 116 return -1; 117 } 118 119 outavail -= moved; 120 buf += moved; 121 len += moved; 122 123 status = CCCryptorFinal(cryptor, buf, outavail, &moved); 124 if(status != kCCSuccess) { 125 free(outbuf); 126 return -1; 127 } 128 129 len += moved; 130 131 plain_msg msg; 132 msg.buf = outbuf; 133 msg.len = len; 134 135 *ret = msg; 136 137 return 0; 138 } 139 140 int main(int argc, char** argv) { 141 char *text = "Hello World!"; 142 size_t textlen = strlen(text); 143 144 char key[32]; 145 // open /dev/urandom and init key with 32 random bytes 146 int devr = open("/dev/urandom", O_RDONLY); 147 if(devr == -1) { 148 return -1; 149 } 150 ssize_t rr = read(devr, key, 32); 151 close(devr); 152 if(rr != 32) { 153 return -1; 154 } 155 156 // encrypt text 157 crypt_msg cmsg; 158 if(aes_encrypt(text, textlen, key, 32, &cmsg)) { 159 fprintf(stderr, "aes_encrypt failed\n"); 160 } 161 162 // decrypt cmsg 163 plain_msg pmsg; 164 if(aes_decrypt(cmsg, key, 32, &pmsg)) { 165 fprintf(stderr, "aes_decrypt failed\n"); 166 } 167 168 printf("decrypted text: %.*s\n", (int)pmsg.len, pmsg.buf); 169 170 return (EXIT_SUCCESS); 171 } 172 173