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[16];
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