Advertisement
Guest User

Untitled

a guest
Apr 12th, 2015
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.27 KB | None | 0 0
  1. #include <stdint.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <memory.h>
  5. #include <string.h>
  6. #include <inttypes.h>
  7.  
  8. #define ROUNDS 32
  9.  
  10. //128-bit integers are necessary for full-compliance, but there is not a single
  11. //use-case I know of that needs to support encrypting more than 2^64-1 bytes
  12. #ifdef __GNUC__
  13. typedef unsigned __int128 u128;
  14. #else
  15. typedef uint64_t u128;
  16. #endif
  17.  
  18. typedef uint8_t byte;
  19.  
  20. typedef struct
  21. {
  22.     uint64_t elements[2];
  23. } vector;
  24.  
  25. typedef struct
  26. {
  27.     byte elements[32];
  28. } block;
  29.  
  30. enum direction
  31. {
  32.     ENCRYPT,
  33.     DECRYPT
  34. };
  35.  
  36. typedef struct state
  37. {
  38.     vector key_schedule[ROUNDS+6][2];
  39.     vector nonce;
  40.     block mac;
  41.  
  42.     u128 counter;
  43.     u128 length;
  44.  
  45.     block (*crypt)(block x, struct state *s);
  46.     enum direction direction;
  47.     char buffer[32];
  48.     uint8_t buffer_len;
  49. } state;
  50.  
  51. const block null_block = {0};
  52.  
  53. static const uint64_t pi[8] = {
  54.     0x243F6A8885A308D3, 0x13198A2E03707345, 0xA4093822299F31D1, 0x082EFA98EC4E6C89,
  55.     0x452821E638D01377, 0xBE5466CF34E90C6D, 0xC0AC29B7C97C50DD, 0x3F84D5B5B5470917
  56. };
  57.  
  58. static vector u128_to_vector(u128 x)
  59. {
  60.     vector t;
  61.     t.elements[0] = 0xFFFFFFFFFFFFFFFF & x;
  62.     t.elements[1] = 0xFFFFFFFFFFFFFFFF & x >> 64;
  63.     return t;
  64. }
  65.  
  66. static uint64_t rotl(uint64_t x, uint8_t r)
  67. {
  68.     return (x << r) | (x >> (64-r));
  69. }
  70.  
  71. static vector vector_xor(vector x, vector y)
  72. {
  73.     x.elements[0] ^= y.elements[0];
  74.     x.elements[1] ^= y.elements[1];
  75.  
  76.     return x;
  77. }
  78.  
  79. vector F(vector x, vector z)
  80. {
  81.     z.elements[0] += x.elements[0];
  82.     z.elements[1] ^= x.elements[1];
  83.     x.elements[0] += z.elements[1];
  84.     x.elements[1] ^= z.elements[0];
  85.  
  86.     x.elements[0] = rotl(x.elements[0], 2);
  87.     x.elements[1] = rotl(x.elements[1],17);
  88.     z.elements[0] = rotl(z.elements[0],31);
  89.     z.elements[1] = rotl(z.elements[1],47);
  90.  
  91.     x.elements[0] = pi[0]*x.elements[0] + pi[1]*x.elements[1]
  92.         + pi[2]*z.elements[0] + pi[3]*z.elements[1];
  93.  
  94.     x.elements[1] = pi[4]*x.elements[0] + pi[5]*x.elements[1]
  95.         + pi[6]*z.elements[0] + pi[7]*z.elements[1];
  96.  
  97.     return x;
  98. }
  99.  
  100. void block_to_vectors(block b, vector x[2])
  101. {
  102.     int i, j, k;
  103.     for (i=0; i<2; i++)
  104.     {
  105.         for (j=0; j<2; j++)
  106.         {
  107.             x[i].elements[j] = 0;
  108.             for (k=0; k<8; k++)
  109.             {
  110.                 x[i].elements[j] |= (uint64_t)b.elements[16*i+8*j+k] << 8*k;
  111.             }
  112.         }
  113.     }
  114. }
  115.  
  116. block vectors_to_block(vector x[2])
  117. {
  118.     block b;
  119.     int i, j, k;
  120.     for (i=0; i<2; i++)
  121.     {
  122.         for (j=0; j<2; j++)
  123.         {
  124.             for (k=0; k<8; k++)
  125.             {
  126.                 b.elements[16*i+8*j+k] = (x[i].elements[j] >> 8*k)&0xFF;
  127.             }
  128.         }
  129.     }
  130.     return b;
  131. }
  132. block block_xor(block x, block y)
  133. {
  134.     int i;
  135.     for (i=0; i<32; i++)
  136.     {
  137.         x.elements[i] ^= y.elements[i];
  138.     }
  139.     return x;
  140. }
  141.  
  142. static block encrypt(block b, state *s)
  143. {
  144.     vector tweak[2];
  145.     vector x[2];
  146.     int i;
  147.    
  148.     block_to_vectors(b, x);
  149.  
  150.     //Compute tweak values from the nonce and counter
  151.     //This is an invertible operation to guarantee no two combinations of nonce/counter
  152.     //will result in identical tweak values
  153.    
  154.     tweak[0] = u128_to_vector(s->counter);
  155.     tweak[1] = s->nonce;
  156.     for (i=0; i<4; i++)
  157.     {
  158.         tweak[i%2] = vector_xor(tweak[i%2],
  159.                 F(
  160.                     vector_xor(tweak[(i+1)%2], s->key_schedule[i][0]),
  161.                     s->key_schedule[i][1]));
  162.     }
  163.    
  164.     //Input whitening
  165.     x[0] = vector_xor(x[0], s->key_schedule[4][0]);
  166.     x[1] = vector_xor(x[1], s->key_schedule[4][1]);
  167.    
  168.     //Perform the actual encryption rounds
  169.     for (i=5; i<ROUNDS+5; i++)
  170.     {
  171.         x[(i+1)%2] = vector_xor(x[(i+1)%2],
  172.                 F(vector_xor(x[i%2], s->key_schedule[i][0]),
  173.                     vector_xor(tweak[i%2], s->key_schedule[i][1])));
  174.  
  175.         if (i-5 == ROUNDS/2)
  176.         {
  177.             s->mac = block_xor(s->mac, vectors_to_block(x));
  178.         }
  179.     }
  180.  
  181.     //Output Whitening
  182.     x[0] = vector_xor(x[0], s->key_schedule[ROUNDS+5][0]);
  183.     x[1] = vector_xor(x[1], s->key_schedule[ROUNDS+5][1]);
  184.  
  185.     return vectors_to_block(x);
  186. }
  187.  
  188. static block decrypt(block b, state *s)
  189. {
  190.     vector tweak[2];
  191.     vector x[2];
  192.     int i;
  193.    
  194.     block_to_vectors(b, x);
  195.  
  196.     //Compute tweak values from the nonce and counter
  197.     //This is an invertible operation to guarantee no two combinations of nonce/counter
  198.     //will result in identical tweak values
  199.    
  200.     tweak[0] = u128_to_vector(s->counter);
  201.     tweak[1] = s->nonce;
  202.     for (i=0; i<4; i++)
  203.     {
  204.         tweak[i%2] = vector_xor(tweak[i%2],
  205.                 F(
  206.                     vector_xor(tweak[(i+1)%2], s->key_schedule[i][0]),
  207.                     s->key_schedule[i][1]));
  208.     }
  209.  
  210.     //Remove Output Whitening
  211.     x[0] = vector_xor(x[0], s->key_schedule[ROUNDS+5][0]);
  212.     x[1] = vector_xor(x[1], s->key_schedule[ROUNDS+5][1]);
  213.    
  214.     //Perform the actual encryption rounds
  215.     for (i=ROUNDS+4; i>= 5; i--)
  216.     {
  217.         if (i-5 == ROUNDS/2)
  218.         {
  219.             s->mac = block_xor(s->mac, vectors_to_block(x));
  220.         }
  221.  
  222.         x[(i+1)%2] = vector_xor(x[(i+1)%2],
  223.                 F(vector_xor(x[i%2], s->key_schedule[i][0]),
  224.                     vector_xor(tweak[i%2], s->key_schedule[i][1])));
  225.     }
  226.  
  227.     //Remove Input whitening
  228.     x[0] = vector_xor(x[0], s->key_schedule[4][0]);
  229.     x[1] = vector_xor(x[1], s->key_schedule[4][1]);
  230.  
  231.     return vectors_to_block(x);
  232. }
  233.  
  234. /* API Functions */
  235.  
  236. void reinit(state *s, vector nonce, enum direction direction)
  237. {
  238.     s->nonce = nonce;
  239.     s->mac = null_block;
  240.     s->counter = 0;
  241.     s->length = 0;
  242.     s->buffer_len = 0;
  243.     s->direction = direction;
  244.     if (direction == ENCRYPT)
  245.     {
  246.         s->crypt = &encrypt;
  247.     }
  248.     else
  249.     {
  250.         s->crypt = &decrypt;
  251.     }
  252. }
  253.  
  254. state *init(vector *key, size_t key_length, vector nonce, enum direction direction)
  255. {
  256.     unsigned int i, j, k;
  257.     vector x[2] = {0};
  258.     u128 counter = 0;
  259.     state *s = calloc(1, sizeof(state));
  260.  
  261.     static const vector e = {.elements = {0xB7E151628AED2A6A,0xBF7158809CF4F3C7}};
  262.  
  263.     for(i=0; i<key_length; i++)
  264.     {
  265.         x[0] = vector_xor(x[0], F(x[1], key[i]));
  266.         x[1] = vector_xor(x[1], F(x[0], e));
  267.     }
  268.     for (i=0; i<ROUNDS+6; i++)
  269.     {
  270.         for (j=0; j<2; j++)
  271.         {
  272.             x[0] = vector_xor(x[0], u128_to_vector(counter++));
  273.             for(k=0; k<key_length; k++)
  274.             {
  275.                 x[0] = vector_xor(x[0], F(x[1], key[k]));
  276.                 x[1] = vector_xor(x[1], F(x[0], e));
  277.             }
  278.             s->key_schedule[i][j] = x[0];
  279.         }
  280.     }
  281.     reinit(s, nonce, direction);
  282.  
  283.     return s;
  284. }
  285.  
  286. void dest(state **s)
  287. {
  288.     //You should really zero memory here, but memset will be optimized, GCC does not
  289.     //support memset_s, and I'm lazy
  290.     free(*s);
  291.     *s = NULL;
  292. }
  293.  
  294. size_t append(char *in, size_t in_len, char *out, size_t out_len, state *s,
  295.         size_t *bytes_written)
  296. {
  297.     size_t in_pos = 0;
  298.     size_t out_pos = 0;
  299.     size_t copy_length;
  300.     block b;
  301.  
  302.     if (s->direction == DECRYPT)
  303.     {
  304.         if (in_len < 32) //We always need to process at least 32 bytes when decrypting
  305.         {
  306.             *bytes_written = 0;
  307.             return 0;
  308.         }
  309.         in_len -= 32; //Exactly 32 bytes will always be placed in the buffer
  310.     }
  311.  
  312.     if (s->buffer_len > 0 && s->buffer_len < 32)
  313.     {
  314.         if (in_len+s->buffer_len >= 32)
  315.         {
  316.             copy_length = 32-s->buffer_len;
  317.         }
  318.         else
  319.         {
  320.             copy_length = in_len;
  321.         }
  322.  
  323.         memcpy(s->buffer+s->buffer_len, in, copy_length);
  324.         in_pos += copy_length;
  325.         s->buffer_len += copy_length;
  326.     }
  327.  
  328.     if (s->buffer_len == 32)
  329.     {
  330.         memcpy(b.elements, s->buffer, 32);
  331.         b = s->crypt(b, s);
  332.         s->counter++;
  333.         memcpy(out+out_pos, b.elements, 32);
  334.        
  335.         out_pos += 32;
  336.         s->buffer_len = 0;
  337.     }
  338.  
  339.     while (in_len-in_pos >= 32 && out_len-in_pos >= 32)
  340.     {
  341.         memcpy(b.elements, in+in_pos, 32);
  342.         in_pos += 32;
  343.         b = s->crypt(b, s);
  344.         s->counter++;
  345.         memcpy(out+out_pos, b.elements, 32);
  346.         out_pos += 32;
  347.     }
  348.  
  349.     if (s->direction == ENCRYPT)
  350.     {
  351.         copy_length = in_len-in_pos;
  352.         if (copy_length > 31)
  353.         {
  354.             copy_length = 31;
  355.         }
  356.     }
  357.     else
  358.     {
  359.         copy_length = 32;
  360.     }
  361.  
  362.     if (copy_length > 0)
  363.     {
  364.         memcpy(s->buffer, in+in_pos, copy_length);
  365.         s->buffer_len = copy_length;
  366.         in_pos += copy_length;
  367.     }
  368.     s->length += out_pos;
  369.     *bytes_written = out_pos;
  370.  
  371.     return in_pos;
  372. }
  373.  
  374. //Result is freed on call to dest(state), you
  375. //should not free result or access after calling dest
  376. char * finalize(size_t *out_length, state *s)
  377. {
  378.     block b;
  379.     //Something to note, I'm using a non-standard padding scheme
  380.     //When setting the padding bytes, each byte is set to the number of plaintext bytes in
  381.     //the final block. When determining the number of plaintext bytes when decrypting,
  382.     //the value of the last byte mod [block_length] is used so there is no invalid padding
  383.     if (s->direction == ENCRYPT)
  384.     {
  385.         //pad and encrypt
  386.         memcpy(b.elements, s->buffer, s->buffer_len);
  387.         memset(b.elements+s->buffer_len, s->buffer_len, 32-s->buffer_len);
  388.         s->buffer_len = 32;
  389.         b = s->crypt(b, s);
  390.         memcpy(s->buffer, b.elements, s->buffer_len);
  391.     }
  392.     else
  393.     {
  394.         //decrypt and remove padding
  395.         if (s->buffer_len == 32)
  396.         {
  397.             memcpy(b.elements, s->buffer, s->buffer_len);
  398.             b = s->crypt(b, s);
  399.             s->buffer_len = b.elements[31] % 32;
  400.             memcpy(s->buffer, b.elements, s->buffer_len);
  401.         }
  402.         else
  403.         {
  404.             return NULL;
  405.         }
  406.     }
  407.  
  408.     *out_length = s->buffer_len;
  409.     s->length += s->buffer_len;
  410.  
  411.     //Finalize MAC computation by encrypting using the length instead of the counter for the
  412.     //tweak value
  413.     s->counter = s->length;
  414.     //s->mac = encrypt(s->mac, s);
  415.  
  416.     //return a reference to the buffer
  417.     return s->buffer;
  418. }
  419.  
  420. char * get_mac(size_t *out_length, state *s)
  421. {
  422.     if (s->length != s->counter) //Not finalized
  423.     {
  424.         *out_length = 0;
  425.         return NULL;
  426.     }
  427.     else
  428.     {
  429.         *out_length = 32;
  430.         return (char *)s->mac.elements;
  431.     }
  432. }
  433.  
  434. int check_mac(char *mac, size_t mac_length, state *s)
  435. {
  436.     int i;
  437.     if (mac_length > 32)
  438.     {
  439.         return 0; //False
  440.     }
  441.     else
  442.     {
  443.         uint8_t check = 0;
  444.         for (i=0; i<mac_length; i++)
  445.         {
  446.             //if any bit differed, check will be non-zero
  447.             check |= s->mac.elements[i] ^ (uint8_t)mac[i];
  448.         }
  449.         return !check;
  450.     }
  451. }
  452.  
  453. //Encrypt or Decrypt all bytes except for the last [trailing_bytes_len] bytes
  454. size_t process_io(FILE *input, FILE *output,
  455.         char *in_buffer, size_t in_buffer_len, size_t trailing_bytes_len,
  456.         char *out_buffer, size_t out_buffer_len,
  457.         state *s)
  458. {
  459.     size_t buffer_len, bytes_read, bytes_written;
  460.     size_t buffer_pos = 0;
  461.     char *tail;
  462.  
  463.     if (trailing_bytes_len > 0)
  464.     {
  465.         buffer_pos = fread(in_buffer, 1, trailing_bytes_len, stdin);
  466.         if (buffer_pos != trailing_bytes_len)
  467.         {
  468.             fprintf(stderr, "Not enough trailing bytes\n");
  469.             exit(1);
  470.         }
  471.     }
  472.     while (trailing_bytes_len < (buffer_len = buffer_pos + fread(in_buffer+buffer_pos, 1,
  473.                     in_buffer_len-buffer_pos, stdin)))
  474.     {
  475.  
  476.         bytes_read = append(in_buffer, buffer_len-trailing_bytes_len, out_buffer,
  477.                 out_buffer_len, s, &bytes_written);
  478.  
  479.         if (bytes_written != fwrite(out_buffer, 1, bytes_written, stdout))
  480.         {
  481.             fprintf(stderr, "Error writing to output\n");
  482.             exit(1);
  483.         }
  484.  
  485.         memmove(in_buffer, in_buffer+bytes_read, buffer_len-bytes_read);
  486.         buffer_pos = buffer_len-bytes_read;
  487.     }
  488.  
  489.     tail = finalize(&bytes_written, s);
  490.  
  491.     if (bytes_written != fwrite(tail, 1, bytes_written, stdout))
  492.     {
  493.         fprintf(stderr, "Error writing to output\n");
  494.         exit(1);
  495.     }
  496.     return buffer_pos;
  497. }
  498.  
  499. int main(int argc, char **argv)
  500. {
  501.     if (argc == 2)
  502.     {
  503.         char direction = argv[1][0];
  504.         vector key = {0};
  505.         vector nonce;
  506.         state *s;
  507.         char *mac;
  508.         size_t bytes_read, bytes_written;
  509.         char out_buffer[8192];
  510.  
  511.         block x = {0};
  512.  
  513.         if (direction == 'e')
  514.         {
  515.             char in_buffer[8192];
  516.             FILE *random = fopen("/dev/random", "rb");
  517.            
  518.             if (random == NULL)
  519.             {
  520.                 fprintf(stderr, "Error reading from /dev/random\n");
  521.                 exit(1);
  522.             }
  523.            
  524.             bytes_read = fread(nonce.elements, 1, sizeof(nonce.elements), random);
  525.  
  526.             fclose(random);
  527.             random = NULL;
  528.             if (bytes_read != 16)
  529.             {
  530.                 fprintf(stderr, "Error reading from /dev/random\n");
  531.                 exit(1);
  532.             }
  533.            
  534.             if (16 != fwrite(nonce.elements, 1, 16, stdout))
  535.             {
  536.                 fprintf(stderr, "Error writing to output\n");
  537.                 exit(1);
  538.             }
  539.            
  540.             s = init(&key, 1, nonce, ENCRYPT);
  541.  
  542.             process_io(stdin, stdout,
  543.                     in_buffer, sizeof(in_buffer), 0, out_buffer, sizeof(out_buffer), s);
  544.  
  545.             mac = get_mac(&bytes_written, s);
  546.  
  547.             if (bytes_written != fwrite(mac, 1, bytes_written, stdout))
  548.             {
  549.                 fprintf(stderr, "Error writing to output\n");
  550.                 exit(1);
  551.             }
  552.             dest(&s);
  553.         }
  554.         else
  555.         {
  556.             char in_buffer[8192+32];
  557.             bytes_read = fread(nonce.elements, 1, sizeof(nonce.elements), stdin);
  558.            
  559.             if (bytes_read != 16)
  560.             {
  561.                 fprintf(stderr, "File did not start with nonce\n");
  562.                 exit(1);
  563.             }
  564.             s = init(&key, 1, nonce, DECRYPT);
  565.            
  566.             bytes_read = process_io(stdin, stdout,
  567.                     in_buffer, sizeof(in_buffer), 32, out_buffer, sizeof(out_buffer), s);
  568.  
  569.             if (!check_mac(in_buffer, bytes_read, s))
  570.             {
  571.                 fprintf(stderr, "MAC check failed\n");
  572.             }
  573.             dest(&s);
  574.         }
  575.     }
  576.     return 0;
  577. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement