Advertisement
Guest User

OCB

a guest
Mar 6th, 2015
313
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.95 KB | None | 0 0
  1. /*------------------------------------------------------------------------
  2. / OCB Version 3 Reference Code (Unoptimized C)   Last modified 12-JUN-2013
  3. /-------------------------------------------------------------------------
  4. / Copyright (c) 2013 Ted Krovetz.
  5. /
  6. / Permission to use, copy, modify, and/or distribute this software for any
  7. / purpose with or without fee is hereby granted, provided that the above
  8. / copyright notice and this permission notice appear in all copies.
  9. /
  10. / THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. / WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. / MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. / ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. / WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. / ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. / OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. /
  18. / Phillip Rogaway holds patents relevant to OCB. See the following for
  19. / his free patent grant: http://www.cs.ucdavis.edu/~rogaway/ocb/grant.htm
  20. /
  21. / Comments are welcome: Ted Krovetz <ted@krovetz.net>
  22. /------------------------------------------------------------------------- */
  23.  
  24. /* This implementation is not optimized and is suceptible to timing attack.
  25. /  It mirrors the OCB RFC to aid in understanding and should not be used
  26. /  for any other purpose. This implementation manipulates data as bytes
  27. /  rather than machine words, which avoids endian issues entirely.
  28. /  To compile: gcc -lcrypto ocb_ref.c                                      */
  29.  
  30. #include <string.h>
  31. #include <openssl/aes.h>
  32. #include <stdint.h>
  33.  
  34. #define CAESAR 0      /* Set non-zero for submission to CAESAR competition */
  35. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  36. #if CAESAR
  37. #include "api.h"
  38. #include "crypto_aead.h"
  39. #define KEYBYTES   CRYPTO_KEYBYTES
  40. #define NONCEBYTES CRYPTO_NPUBBYTES
  41. #define TAGBYTES   CRYPTO_ABYTES
  42. #else
  43. #define KEYBYTES   (128/8)
  44. #define NONCEBYTES (96/8)
  45. #define TAGBYTES   (128/8)
  46. #endif
  47.  
  48. #if !(KEYBYTES==16 || KEYBYTES==24 || KEYBYTES==32) ||  \
  49.      (NONCEBYTES > 15 || NONCEBYTES < 0) ||             \
  50.      (TAGBYTES > 16 || TAGBYTES < 1)
  51. #error -- KEYBYTES, NONCEBYTES, or TAGBYTES is an illegal value
  52. #endif
  53.  
  54. typedef uint8_t block[16];
  55.  
  56. /* ------------------------------------------------------------------------- */
  57.  
  58. static void xor_block(block d, block s1, block s2) {
  59.     unsigned i;
  60.     for (i=0; i<16; i++)
  61.         d[i] = s1[i] ^ s2[i];
  62. }
  63.  
  64. /* ------------------------------------------------------------------------- */
  65.  
  66. static void double_block(block d, block s) {
  67.     unsigned i;
  68.     uint8_t tmp = s[0];
  69.     for (i=0; i<15; i++)
  70.         d[i] = (s[i] << 1) | (s[i+1] >> 7);
  71.     d[15] = (s[15] << 1) ^ ((tmp >> 7) * 135);
  72. }
  73.  
  74. /* ------------------------------------------------------------------------- */
  75.  
  76. static void calc_L_i(block l, block ldollar, unsigned i) {
  77.     double_block(l, ldollar);         /* l is now L_0               */
  78.     for ( ; (i&1)==0 ; i>>=1)
  79.         double_block(l,l);            /* double for each trailing 0 */
  80. }
  81.  
  82. /* ------------------------------------------------------------------------- */
  83.  
  84. static void hash(block result, uint8_t *k,
  85.                  uint8_t *a, unsigned abytes) {
  86.     AES_KEY aes_key;
  87.     block lstar, ldollar, offset, sum, tmp;
  88.     unsigned i;
  89.  
  90.     /* Key-dependent variables */
  91.  
  92.     /* L_* = ENCIPHER(K, zeros(128)) */
  93.     AES_set_encrypt_key(k, KEYBYTES*8, &aes_key);
  94.     memset(tmp, 0, 16);
  95.     AES_encrypt(tmp, lstar, &aes_key);
  96.     /* L_$ = double(L_*) */
  97.     double_block(ldollar, lstar);
  98.  
  99.     /* Process any whole blocks */
  100.  
  101.     /* Sum_0 = zeros(128) */
  102.     memset(sum, 0, 16);
  103.     /* Offset_0 = zeros(128) */
  104.     memset(offset, 0, 16);
  105.     for (i=1; i<=abytes/16; i++, a = a + 16) {
  106.         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
  107.         calc_L_i(tmp, ldollar, i);
  108.         xor_block(offset, offset, tmp);
  109.         /* Sum_i = Sum_{i-1} xor ENCIPHER(K, A_i xor Offset_i) */
  110.         xor_block(tmp, offset, a);
  111.         AES_encrypt(tmp, tmp, &aes_key);
  112.         xor_block(sum, sum, tmp);
  113.     }
  114.  
  115.     /* Process any final partial block; compute final hash value */
  116.  
  117.     abytes = abytes % 16;  /* Bytes in final block */
  118.     if (abytes > 0) {
  119.         /* Offset_* = Offset_m xor L_* */
  120.         xor_block(offset, offset, lstar);
  121.         /* tmp = (A_* || 1 || zeros(127-bitlen(A_*))) xor Offset_* */
  122.         memset(tmp, 0, 16);
  123.         memcpy(tmp, a, abytes);
  124.         tmp[abytes] = 0x80;
  125.         xor_block(tmp, offset, tmp);
  126.         /* Sum = Sum_m xor ENCIPHER(K, tmp) */
  127.         AES_encrypt(tmp, tmp, &aes_key);
  128.         xor_block(sum, tmp, sum);
  129.     }
  130.  
  131.     memcpy(result, sum, 16);
  132. }
  133.  
  134. /* ------------------------------------------------------------------------- */
  135.  
  136. static int ocb_crypt(uint8_t *out, uint8_t *k, uint8_t *n,
  137.                      uint8_t *a, unsigned abytes,
  138.                      uint8_t *in, unsigned inbytes, int encrypting) {
  139.     AES_KEY aes_encrypt_key, aes_decrypt_key;
  140.     block lstar, ldollar, sum, offset, ktop, pad, nonce, tag, tmp;
  141.     uint8_t stretch[24];
  142.     unsigned bottom, byteshift, bitshift, i;
  143.  
  144.     /* Setup AES and strip ciphertext of its tag */
  145.     if ( ! encrypting ) {
  146.          if (inbytes < TAGBYTES) return -1;
  147.          inbytes -= TAGBYTES;
  148.          AES_set_decrypt_key(k, KEYBYTES*8, &aes_decrypt_key);
  149.     }
  150.     AES_set_encrypt_key(k, KEYBYTES*8, &aes_encrypt_key);
  151.  
  152.     /* Key-dependent variables */
  153.  
  154.     /* L_* = ENCIPHER(K, zeros(128)) */
  155.     memset(tmp, 0, 16);
  156.     AES_encrypt(tmp, lstar, &aes_encrypt_key);
  157.     /* L_$ = double(L_*) */
  158.     double_block(ldollar, lstar);
  159.  
  160.     /* Nonce-dependent and per-encryption variables */
  161.  
  162.     /* Nonce = zeros(127-bitlen(N)) || 1 || N */
  163.     memset(nonce,0,16);
  164.     memcpy(&nonce[16-NONCEBYTES],n,NONCEBYTES);
  165.     nonce[0] = (uint8_t)(((TAGBYTES * 8) % 128) << 1);
  166.     nonce[16-NONCEBYTES-1] |= 0x01;
  167.     /* bottom = str2num(Nonce[123..128]) */
  168.     bottom = nonce[15] & 0x3F;
  169.     /* Ktop = ENCIPHER(K, Nonce[1..122] || zeros(6)) */
  170.     nonce[15] &= 0xC0;
  171.     AES_encrypt(nonce, ktop, &aes_encrypt_key);
  172.     /* Stretch = Ktop || (Ktop[1..64] xor Ktop[9..72]) */
  173.     memcpy(stretch, ktop, 16);
  174.     memcpy(tmp, &ktop[1], 8);
  175.     xor_block(tmp, tmp, ktop);
  176.     memcpy(&stretch[16],tmp,8);
  177.     /* Offset_0 = Stretch[1+bottom..128+bottom] */
  178.     byteshift = bottom/8;
  179.     bitshift  = bottom%8;
  180.     if (bitshift != 0)
  181.         for (i=0; i<16; i++)
  182.             offset[i] = (stretch[i+byteshift] << bitshift) |
  183.                         (stretch[i+byteshift+1] >> (8-bitshift));
  184.     else
  185.         for (i=0; i<16; i++)
  186.             offset[i] = stretch[i+byteshift];
  187.     /* Checksum_0 = zeros(128) */
  188.     memset(sum, 0, 16);
  189.  
  190.     /* Process any whole blocks */
  191.  
  192.     for (i=1; i<=inbytes/16; i++, in=in+16, out=out+16) {
  193.         /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
  194.         calc_L_i(tmp, ldollar, i);
  195.         xor_block(offset, offset, tmp);
  196.  
  197.         xor_block(tmp, offset, in);
  198.         if (encrypting) {
  199.             /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) */
  200.             AES_encrypt(tmp, tmp, &aes_encrypt_key);
  201.             xor_block(out, offset, tmp);
  202.             /* Checksum_i = Checksum_{i-1} xor P_i */
  203.             xor_block(sum, in, sum);
  204.         } else {
  205.             /* P_i = Offset_i xor DECIPHER(K, C_i xor Offset_i) */
  206.             AES_decrypt(tmp, tmp, &aes_decrypt_key);
  207.             xor_block(out, offset, tmp);
  208.             /* Checksum_i = Checksum_{i-1} xor P_i */
  209.             xor_block(sum, out, sum);
  210.         }
  211.     }
  212.  
  213.     /* Process any final partial block and compute raw tag */
  214.  
  215.     inbytes = inbytes % 16;  /* Bytes in final block */
  216.     if (inbytes > 0) {
  217.         /* Offset_* = Offset_m xor L_* */
  218.         xor_block(offset, offset, lstar);
  219.         /* Pad = ENCIPHER(K, Offset_*) */
  220.         AES_encrypt(offset, pad, &aes_encrypt_key);
  221.  
  222.         if (encrypting) {
  223.             /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */
  224.             memset(tmp, 0, 16);
  225.             memcpy(tmp, in, inbytes);
  226.             tmp[inbytes] = 0x80;
  227.             xor_block(sum, tmp, sum);
  228.             /* C_* = P_* xor Pad[1..bitlen(P_*)] */
  229.             xor_block(pad, tmp, pad);
  230.             memcpy(out, pad, inbytes);
  231.             out = out + inbytes;
  232.         } else {
  233.             /* P_* = C_* xor Pad[1..bitlen(C_*)] */
  234.             memcpy(tmp, pad, 16);
  235.             memcpy(tmp, in, inbytes);
  236.             xor_block(tmp, pad, tmp);
  237.             tmp[inbytes] = 0x80;     /* tmp == P_* || 1 || zeros(127-bitlen(P_*)) */
  238.             memcpy(out, tmp, inbytes);
  239.             /* Checksum_* = Checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*))) */
  240.             xor_block(sum, tmp, sum);
  241.             in = in + inbytes;
  242.         }
  243.     }
  244.  
  245.     /* Tag = ENCIPHER(K, Checksum xor Offset xor L_$) xor HASH(K,A) */
  246.     xor_block(tmp, sum, offset);
  247.     xor_block(tmp, tmp, ldollar);
  248.     AES_encrypt(tmp, tag, &aes_encrypt_key);
  249.     hash(tmp, k, a, abytes);
  250.     xor_block(tag, tmp, tag);
  251.  
  252.     if (encrypting) {
  253.         memcpy(out, tag, TAGBYTES);
  254.         return 0;
  255.     } else
  256.         return (memcmp(in,tag,TAGBYTES) ? -1 : 0);     /* Check for validity */
  257. }
  258.  
  259. /* ------------------------------------------------------------------------- */
  260.  
  261. #define OCB_ENCRYPT 1
  262. #define OCB_DECRYPT 0
  263.  
  264. void ocb_encrypt(uint8_t *c, uint8_t *k, uint8_t *n,
  265.                  uint8_t *a, unsigned abytes,
  266.                  uint8_t *p, unsigned pbytes) {
  267.     ocb_crypt(c, k, n, a, abytes, p, pbytes, OCB_ENCRYPT);
  268. }
  269.  
  270. /* ------------------------------------------------------------------------- */
  271.  
  272. int ocb_decrypt(uint8_t *p, uint8_t *k, uint8_t *n,
  273.                 uint8_t *a, unsigned abytes,
  274.                 uint8_t *c, unsigned cbytes) {
  275.     return ocb_crypt(p, k, n, a, abytes, c, cbytes, OCB_DECRYPT);
  276. }
  277.  
  278.  
  279.  
  280. #include <stdio.h>
  281. #include <stdlib.h>
  282. #define PLAIN_SIZE 8
  283. int main() {
  284.     uint8_t zeroes[PLAIN_SIZE];
  285.     uint8_t nonce[12] = {0,};
  286.     uint8_t p[PLAIN_SIZE+8] = {0,};
  287.     uint8_t final[16];
  288.     uint8_t *c;
  289.     unsigned i, next;
  290.     int result;
  291.     for (i=0; i<(PLAIN_SIZE); i++) {
  292.         zeroes[i]=2;
  293.         p[i]=5;
  294.         }
  295.     p[i+8]=5;
  296.     printf("Nonece: %d\n",NONCEBYTES);
  297.     /* Encrypt and output RFC vector */
  298.     c = malloc(22400);
  299.     next = 0;
  300.     for (i=0; i<PLAIN_SIZE; i++) {
  301.         nonce[10] = i;
  302.         ocb_encrypt(c+next, zeroes, nonce, zeroes, i, zeroes, i);
  303.         next = next + i + TAGBYTES;
  304.         ocb_encrypt(c+next, zeroes, nonce, zeroes, 0, zeroes, i);
  305.         next = next + i + TAGBYTES;
  306.         ocb_encrypt(c+next, zeroes, nonce, zeroes, i, zeroes, 0);
  307.         next = next + TAGBYTES;
  308.     }
  309.     nonce[10] = 0;
  310.     ocb_encrypt(final, zeroes, nonce, c, next, zeroes, 0);
  311.     if (NONCEBYTES == 12) {
  312.         printf("AEAD_AES_%d_OCB_TAGLEN%d Output: ", KEYBYTES*8, TAGBYTES*8);
  313.         for (i=0; i<TAGBYTES; i++) printf("%02X", final[i]); printf("\n");
  314.     }
  315.  
  316.     /* Decrypt and test for all zeros and authenticity */
  317.     result = ocb_decrypt(p, zeroes, nonce, c, next, final, TAGBYTES);
  318.     if (result) { printf("FAIL\n"); return 0; }
  319.     next = 0;
  320.     for (i=0; i<PLAIN_SIZE; i++) {
  321.         nonce[10] = i;
  322.         result = ocb_decrypt(p, zeroes, nonce, zeroes, i, c+next, i+TAGBYTES);
  323.         if (result || memcmp(p,zeroes,i)) { printf("FAIL\n"); return 0; }
  324.         next = next + i + TAGBYTES;
  325.         result = ocb_decrypt(p, zeroes, nonce, zeroes, 0, c+next, i+TAGBYTES);
  326.         if (result || memcmp(p,zeroes,i)) { printf("FAIL\n"); return 0; }
  327.         next = next + i + TAGBYTES;
  328.         result = ocb_decrypt(p, zeroes, nonce, zeroes, i, c+next, TAGBYTES);
  329.         if (result || memcmp(p,zeroes,i)) { printf("FAIL\n"); return 0; }
  330.         next = next + TAGBYTES;
  331.     }
  332.     for (i=0; i<(PLAIN_SIZE); i++) printf("%d",  zeroes[i]); printf("\n");
  333.     for (i=0; i<(PLAIN_SIZE); i++) printf("%d", p[i]); printf("\n");
  334.     free(c);
  335.  
  336.  
  337.     return 0;
  338. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement