Advertisement
thenuke321

Untitled

Feb 25th, 2015
353
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.84 KB | None | 0 0
  1. // AES Implementation by X-N2O
  2. // Started:  15:41:35 - 18 Nov 2009
  3. // Finished: 20:03:59 - 21 Nov 2009
  4. // Logarithm, S-Box, and RCON tables are not hardcoded
  5. // Instead they are generated when the program starts
  6. // All of the code below is based from the AES specification
  7. // You can find it at http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
  8. // You may use this code as you wish, but do not remove this comment
  9. // This is only a proof of concept, and should not be considered as the most efficient implementation
  10.  
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <stdio.h>
  14.  
  15. #define AES_RPOL      0x011b // reduction polynomial (x^8 + x^4 + x^3 + x + 1)
  16. #define AES_GEN    0x03   // gf(2^8) generator  (x + 1)
  17. #define AES_SBOX_CC   0x63   // S-Box C constant
  18.  
  19. #define KEY_128 (128/8)
  20. #define KEY_192 (192/8)
  21. #define KEY_256 (256/8)
  22.  
  23. #define aes_mul(a, b) ((a)&&(b)?g_aes_ilogt[(g_aes_logt[(a)]+g_aes_logt[(b)])%0xff]:0)
  24. #define aes_inv(a)  ((a)?g_aes_ilogt[0xff-g_aes_logt[(a)]]:0)
  25.  
  26. unsigned char g_aes_logt[256], g_aes_ilogt[256];
  27. unsigned char g_aes_sbox[256], g_aes_isbox[256];
  28.  
  29. typedef struct {
  30.     unsigned char state[4][4];
  31.     int kcol;
  32.     size_t rounds;
  33.     unsigned long keysched[0];
  34. } aes_ctx_t;
  35.  
  36. void aes_init();
  37. aes_ctx_t *aes_alloc_ctx(unsigned char *key, size_t keyLen);
  38. inline unsigned long aes_subword(unsigned long w);
  39. inline unsigned long aes_rotword(unsigned long w);
  40. void aes_keyexpansion(aes_ctx_t *ctx);
  41.  
  42. inline unsigned char aes_mul_manual(unsigned char a, unsigned char b); // use aes_mul instead
  43.  
  44. void aes_subbytes(aes_ctx_t *ctx);
  45. void aes_shiftrows(aes_ctx_t *ctx);
  46. void aes_mixcolumns(aes_ctx_t *ctx);
  47. void aes_addroundkey(aes_ctx_t *ctx, int round);
  48. void aes_encrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16]);
  49.  
  50. void aes_invsubbytes(aes_ctx_t *ctx);
  51. void aes_invshiftrows(aes_ctx_t *ctx);
  52. void aes_invmixcolumns(aes_ctx_t *ctx);
  53. void aes_decrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16]);
  54.  
  55. void aes_free_ctx(aes_ctx_t *ctx);
  56.  
  57. void init_aes()
  58. {
  59.     int i;
  60.     unsigned char gen;
  61.  
  62.     // build logarithm table and it's inverse
  63.     gen = 1;
  64.     for(i = 0; i < 0xff; i++) {
  65.         g_aes_logt[gen]  = i;
  66.         g_aes_ilogt[i]   = gen;
  67.         gen = aes_mul_manual(gen, AES_GEN);
  68.     }
  69.  
  70.     // build S-Box and it's inverse
  71.     for(i = 0; i <= 0xff; i++) {
  72.         char bi;
  73.         unsigned char inv = aes_inv(i);
  74.  
  75.         g_aes_sbox[i] = 0;
  76.         for(bi = 0; bi < 8; bi++) {
  77.             // based on transformation 5.1
  78.             // could also be done with a loop based on the matrix
  79.             g_aes_sbox[i] |= ((inv & (1<<bi)?1:0)
  80.                         ^ (inv & (1 << ((bi+4) & 7))?1:0)
  81.                         ^ (inv & (1 << ((bi+5) & 7))?1:0)
  82.                         ^ (inv & (1 << ((bi+6) & 7))?1:0)
  83.                         ^ (inv & (1 << ((bi+7) & 7))?1:0)
  84.                         ^ (AES_SBOX_CC & (1 << bi)?1:0)
  85.             ) << bi;
  86.         }
  87.         g_aes_isbox[g_aes_sbox[i]] = i;
  88.     }
  89.     // warning: quickhack
  90.     g_aes_sbox[1] = 0x7c;
  91.     g_aes_isbox[0x7c] = 1;
  92.     g_aes_isbox[0x63] = 0;
  93. }
  94.  
  95. aes_ctx_t *aes_alloc_ctx(unsigned char *key, size_t keyLen)
  96. {
  97.     aes_ctx_t *ctx;
  98.     size_t rounds;
  99.     size_t ks_size;
  100.  
  101.     switch(keyLen) {
  102.         case 16: // 128-bit key
  103.             rounds = 10;
  104.             break;
  105.  
  106.         case 24: // 192-bit key
  107.             rounds = 12;
  108.             break;
  109.  
  110.         case 32: // 256-bit key
  111.             rounds = 14;
  112.             break;
  113.  
  114.         defaut:
  115.             return NULL;
  116.     }
  117.  
  118.     ks_size = 4*(rounds+1)*sizeof(unsigned long);
  119.     ctx = malloc(sizeof(aes_ctx_t)+ks_size);
  120.     if(ctx) {
  121.         ctx->rounds = rounds;
  122.         ctx->kcol = keyLen/4;
  123.         memcpy(ctx->keysched, key, keyLen);
  124.         ctx->keysched[43] = 0;
  125.         aes_keyexpansion(ctx);
  126.     }
  127.  
  128.     return ctx;
  129. }
  130.  
  131. inline unsigned long aes_subword(unsigned long w)
  132. {
  133.     return g_aes_sbox[w & 0x000000ff] |
  134.         (g_aes_sbox[(w & 0x0000ff00) >> 8] << 8) |
  135.         (g_aes_sbox[(w & 0x00ff0000) >> 16] << 16) |
  136.         (g_aes_sbox[(w & 0xff000000) >> 24] << 24);
  137. }
  138.  
  139. inline unsigned long aes_rotword(unsigned long w)
  140. {
  141.     // May seem a bit different from the spec
  142.     // It was changed because unsigned long is represented with little-endian convention on x86
  143.     // Should not depend on architecture, but this is only a POC
  144.     return ((w & 0x000000ff) << 24) |
  145.         ((w & 0x0000ff00) >> 8) |
  146.         ((w & 0x00ff0000) >> 8) |
  147.         ((w & 0xff000000) >> 8);
  148. }
  149.  
  150. void aes_keyexpansion(aes_ctx_t *ctx)
  151. {
  152.     unsigned long temp;
  153.     unsigned long rcon;
  154.     register int i;
  155.  
  156.     rcon = 0x00000001;
  157.     for(i = ctx->kcol; i < (4*(ctx->rounds+1)); i++) {
  158.         temp = ctx->keysched[i-1];
  159.         if(!(i%ctx->kcol)) {
  160.             temp = aes_subword(aes_rotword(temp)) ^ rcon;
  161.             rcon = aes_mul(rcon, 2);
  162.         } else if(ctx->kcol > 6 && i%ctx->kcol == 4)
  163.             temp = aes_subword(temp);
  164.         ctx->keysched[i] = ctx->keysched[i-ctx->kcol] ^ temp;
  165.     }
  166. }
  167.  
  168. inline unsigned char aes_mul_manual(unsigned char a, unsigned char b)
  169. {
  170.     register unsigned short ac;
  171.     register unsigned char ret;
  172.  
  173.     ac = a;
  174.     ret = 0;
  175.     while(b) {
  176.         if(b & 0x01)
  177.             ret ^= ac;
  178.         ac <<= 1;
  179.         b >>= 1;
  180.         if(ac & 0x0100)
  181.             ac ^= AES_RPOL;
  182.     }
  183.  
  184.     return ret;
  185. }
  186.  
  187. void aes_subbytes(aes_ctx_t *ctx)
  188. {
  189.     int i;
  190.  
  191.     for(i = 0; i < 16; i++) {
  192.         int x, y;
  193.  
  194.         x = i & 0x03;
  195.         y = i >> 2;
  196.         ctx->state[x][y] = g_aes_sbox[ctx->state[x][y]];
  197.     }
  198. }
  199.  
  200. void aes_shiftrows(aes_ctx_t *ctx)
  201. {
  202.     unsigned char nstate[4][4];
  203.     int i;
  204.  
  205.     for(i = 0; i < 16; i++) {
  206.         int x, y;
  207.  
  208.         x = i & 0x03;
  209.         y = i >> 2;
  210.         nstate[x][y] = ctx->state[x][(y+x) & 0x03];
  211.     }
  212.  
  213.     memcpy(ctx->state, nstate, sizeof(ctx->state));
  214. }
  215.  
  216. void aes_mixcolumns(aes_ctx_t *ctx)
  217. {
  218.     unsigned char nstate[4][4];
  219.     int i;
  220.    
  221.     for(i = 0; i < 4; i++) {
  222.         nstate[0][i] = aes_mul(0x02, ctx->state[0][i]) ^
  223.                 aes_mul(0x03, ctx->state[1][i]) ^
  224.                 ctx->state[2][i] ^
  225.                 ctx->state[3][i];
  226.         nstate[1][i] = ctx->state[0][i] ^
  227.                 aes_mul(0x02, ctx->state[1][i]) ^
  228.                 aes_mul(0x03, ctx->state[2][i]) ^
  229.                 ctx->state[3][i];
  230.         nstate[2][i] = ctx->state[0][i] ^
  231.                 ctx->state[1][i] ^
  232.                 aes_mul(0x02, ctx->state[2][i]) ^
  233.                 aes_mul(0x03, ctx->state[3][i]);
  234.         nstate[3][i] = aes_mul(0x03, ctx->state[0][i]) ^
  235.                 ctx->state[1][i] ^
  236.                 ctx->state[2][i] ^
  237.                 aes_mul(0x02, ctx->state[3][i]);
  238.     }
  239.  
  240.     memcpy(ctx->state, nstate, sizeof(ctx->state));
  241. }
  242.  
  243. void aes_addroundkey(aes_ctx_t *ctx, int round)
  244. {
  245.     int i;
  246.  
  247.     for(i = 0; i < 16; i++) {
  248.         int x, y;
  249.  
  250.         x = i & 0x03;
  251.         y = i >> 2;
  252.         ctx->state[x][y] = ctx->state[x][y] ^
  253.             ((ctx->keysched[round*4+y] & (0xff << (x*8))) >> (x*8));
  254.     }
  255. }
  256.  
  257. void aes_encrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16])
  258. {
  259.     int i;
  260.  
  261.     // copy input to state
  262.     for(i = 0; i < 16; i++)
  263.         ctx->state[i & 0x03][i >> 2] = input[i];
  264.  
  265.     aes_addroundkey(ctx, 0);
  266.  
  267.     for(i = 1; i < ctx->rounds; i++) {
  268.         aes_subbytes(ctx);
  269.         aes_shiftrows(ctx);
  270.         aes_mixcolumns(ctx);
  271.         aes_addroundkey(ctx, i);
  272.     }
  273.  
  274.     aes_subbytes(ctx);
  275.     aes_shiftrows(ctx);
  276.     aes_addroundkey(ctx, ctx->rounds);
  277.  
  278.     // copy state to output
  279.     for(i = 0; i < 16; i++)
  280.         output[i] = ctx->state[i & 0x03][i >> 2];
  281. }
  282.  
  283. void aes_invshiftrows(aes_ctx_t *ctx)
  284. {
  285.     unsigned char nstate[4][4];
  286.     int i;
  287.  
  288.     for(i = 0; i < 16; i++) {
  289.         int x, y;
  290.  
  291.         x = i & 0x03;
  292.         y = i >> 2;
  293.         nstate[x][(y+x) & 0x03] = ctx->state[x][y];
  294.     }
  295.  
  296.     memcpy(ctx->state, nstate, sizeof(ctx->state));
  297. }
  298.  
  299. void aes_invsubbytes(aes_ctx_t *ctx)
  300. {
  301.     int i;
  302.  
  303.     for(i = 0; i < 16; i++) {
  304.         int x, y;
  305.  
  306.         x = i & 0x03;
  307.         y = i >> 2;
  308.         ctx->state[x][y] = g_aes_isbox[ctx->state[x][y]];
  309.     }
  310. }
  311.  
  312. void aes_invmixcolumns(aes_ctx_t *ctx)
  313. {
  314.     unsigned char nstate[4][4];
  315.     int i;
  316.    
  317.     for(i = 0; i < 4; i++) {
  318.         nstate[0][i] = aes_mul(0x0e, ctx->state[0][i]) ^
  319.                 aes_mul(0x0b, ctx->state[1][i]) ^
  320.                 aes_mul(0x0d, ctx->state[2][i]) ^
  321.                 aes_mul(0x09, ctx->state[3][i]);
  322.         nstate[1][i] = aes_mul(0x09, ctx->state[0][i]) ^
  323.                 aes_mul(0x0e, ctx->state[1][i]) ^
  324.                 aes_mul(0x0b, ctx->state[2][i]) ^
  325.                 aes_mul(0x0d, ctx->state[3][i]);
  326.         nstate[2][i] = aes_mul(0x0d, ctx->state[0][i]) ^
  327.                 aes_mul(0x09, ctx->state[1][i]) ^
  328.                 aes_mul(0x0e, ctx->state[2][i]) ^
  329.                 aes_mul(0x0b, ctx->state[3][i]);
  330.         nstate[3][i] = aes_mul(0x0b, ctx->state[0][i]) ^
  331.                 aes_mul(0x0d, ctx->state[1][i]) ^
  332.                 aes_mul(0x09, ctx->state[2][i]) ^
  333.                 aes_mul(0x0e, ctx->state[3][i]);
  334.     }
  335.  
  336.     memcpy(ctx->state, nstate, sizeof(ctx->state));
  337. }
  338.  
  339. void aes_decrypt(aes_ctx_t *ctx, unsigned char input[16], unsigned char output[16])
  340. {
  341.     int i, j;
  342.  
  343.     // copy input to state
  344.     for(i = 0; i < 16; i++)
  345.         ctx->state[i & 0x03][i >> 2] = input[i];
  346.  
  347.     aes_addroundkey(ctx, ctx->rounds);
  348.     for(i = ctx->rounds-1; i >= 1; i--) {
  349.         aes_invshiftrows(ctx);
  350.         aes_invsubbytes(ctx);
  351.         aes_addroundkey(ctx, i);
  352.         aes_invmixcolumns(ctx);
  353.     }
  354.  
  355.     aes_invshiftrows(ctx);
  356.     aes_invsubbytes(ctx);
  357.     aes_addroundkey(ctx, 0);
  358.  
  359.     // copy state to output
  360.     for(i = 0; i < 16; i++)
  361.         output[i] = ctx->state[i & 0x03][i >> 2];
  362. }
  363.  
  364. void aes_free_ctx(aes_ctx_t *ctx)
  365. {
  366.     free(ctx);
  367. }
  368.  
  369. int main(int argc, char *argv[])
  370. {
  371.     unsigned char key[KEY_128] = "uber strong key!";
  372.     unsigned char ptext[16] = "Attack at dawn!";
  373.     unsigned char ctext[16];
  374.     unsigned char decptext[16];
  375.     aes_ctx_t *ctx;
  376.  
  377.     init_aes();
  378.     ctx = aes_alloc_ctx(key, sizeof(key));
  379.     if(!ctx) {
  380.         perror("aes_alloc_ctx");
  381.         return EXIT_FAILURE;
  382.     }
  383.     aes_encrypt(ctx, ptext, ctext);
  384.     aes_decrypt(ctx, ctext, decptext);
  385.     puts(decptext);
  386.  
  387.     aes_free_ctx(ctx);
  388.     return EXIT_SUCCESS;
  389. }
  390.  
  391. /*
  392. C:\Users\Heavy\Desktop>cl main.cpp
  393. Microsoft (R) C/C++ Optimizing Compiler Version 17.00.50727.1 for x64
  394. Copyright (C) Microsoft Corporation.  All rights reserved.
  395.  
  396. main.cpp
  397. main.cpp(119) : error C2440: '=' : cannot convert from 'void *' to 'aes_ctx_t *'
  398.  
  399.         Conversion from 'void*' to pointer to non-'void' requires an explicit ca
  400. st
  401. main.cpp(371) : error C2117: 'key' : array bounds overflow
  402.         main.cpp(371) : see declaration of 'key'
  403.         main.cpp(371) : see declaration of 'key'
  404. main.cpp(385) : error C2664: 'puts' : cannot convert parameter 1 from 'unsigned
  405. char [16]' to 'const char *'
  406.         Types pointed to are unrelated; conversion requires reinterpret_cast, C-
  407. style cast or function-style cast
  408.  
  409. C:\Users\Heavy\Desktop>
  410. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement