chacha_private.h

Go to the documentation of this file.
00001 /*
00002  * Taken from OpenBSD CVS src/lib/libc/crypt/chacha_private.h on
00003  * May 12, 2014.
00004  */
00005 
00006 /*
00007 chacha-merged.c version 20080118
00008 D. J. Bernstein
00009 Public domain.
00010 */
00011 
00012 typedef unsigned char u8;
00013 typedef unsigned int u32;
00014 
00015 typedef struct
00016 {
00017   u32 input[16]; /* could be compressed */
00018 } chacha_ctx;
00019 
00020 #define U8C(v) (v##U)
00021 #define U32C(v) (v##U)
00022 
00023 #define U8V(v) ((u8)(v) & U8C(0xFF))
00024 #define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
00025 
00026 #define ROTL32(v, n) \
00027   (U32V((v) << (n)) | ((v) >> (32 - (n))))
00028 
00029 #define U8TO32_LITTLE(p) \
00030   (((u32)((p)[0])      ) | \
00031    ((u32)((p)[1]) <<  8) | \
00032    ((u32)((p)[2]) << 16) | \
00033    ((u32)((p)[3]) << 24))
00034 
00035 #define U32TO8_LITTLE(p, v) \
00036   do { \
00037     (p)[0] = U8V((v)      ); \
00038     (p)[1] = U8V((v) >>  8); \
00039     (p)[2] = U8V((v) >> 16); \
00040     (p)[3] = U8V((v) >> 24); \
00041   } while (0)
00042 
00043 #define ROTATE(v,c) (ROTL32(v,c))
00044 #define XOR(v,w) ((v) ^ (w))
00045 #define PLUS(v,w) (U32V((v) + (w)))
00046 #define PLUSONE(v) (PLUS((v),1))
00047 
00048 #define QUARTERROUND(a,b,c,d) \
00049   a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
00050   c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
00051   a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
00052   c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
00053 
00054 static const char sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
00055                                 '2', '-', 'b', 'y', 't', 'e', ' ', 'k' };
00056 static const char tau[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '1',
00057                               '6', '-', 'b', 'y', 't', 'e', ' ', 'k' };
00058 
00059 static void
00060 chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
00061 {
00062   const char *constants;
00063 
00064   UNUSED(ivbits);
00065 
00066   x->input[4] = U8TO32_LITTLE(k + 0);
00067   x->input[5] = U8TO32_LITTLE(k + 4);
00068   x->input[6] = U8TO32_LITTLE(k + 8);
00069   x->input[7] = U8TO32_LITTLE(k + 12);
00070   if (kbits == 256) { /* recommended */
00071     k += 16;
00072     constants = sigma;
00073   } else { /* kbits == 128 */
00074     constants = tau;
00075   }
00076   x->input[8] = U8TO32_LITTLE(k + 0);
00077   x->input[9] = U8TO32_LITTLE(k + 4);
00078   x->input[10] = U8TO32_LITTLE(k + 8);
00079   x->input[11] = U8TO32_LITTLE(k + 12);
00080   x->input[0] = U8TO32_LITTLE(constants + 0);
00081   x->input[1] = U8TO32_LITTLE(constants + 4);
00082   x->input[2] = U8TO32_LITTLE(constants + 8);
00083   x->input[3] = U8TO32_LITTLE(constants + 12);
00084 }
00085 
00086 static void
00087 chacha_ivsetup(chacha_ctx *x,const u8 *iv)
00088 {
00089   x->input[12] = 0;
00090   x->input[13] = 0;
00091   x->input[14] = U8TO32_LITTLE(iv + 0);
00092   x->input[15] = U8TO32_LITTLE(iv + 4);
00093 }
00094 
00095 static void
00096 chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes)
00097 {
00098   u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
00099   u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
00100   u8 *ctarget = NULL;
00101   u8 tmp[64];
00102   u_int i;
00103 
00104   if (!bytes) return;
00105 
00106   j0 = x->input[0];
00107   j1 = x->input[1];
00108   j2 = x->input[2];
00109   j3 = x->input[3];
00110   j4 = x->input[4];
00111   j5 = x->input[5];
00112   j6 = x->input[6];
00113   j7 = x->input[7];
00114   j8 = x->input[8];
00115   j9 = x->input[9];
00116   j10 = x->input[10];
00117   j11 = x->input[11];
00118   j12 = x->input[12];
00119   j13 = x->input[13];
00120   j14 = x->input[14];
00121   j15 = x->input[15];
00122 
00123   for (;;) {
00124     if (bytes < 64) {
00125       for (i = 0;i < bytes;++i) tmp[i] = m[i];
00126       m = tmp;
00127       ctarget = c;
00128       c = tmp;
00129     }
00130     x0 = j0;
00131     x1 = j1;
00132     x2 = j2;
00133     x3 = j3;
00134     x4 = j4;
00135     x5 = j5;
00136     x6 = j6;
00137     x7 = j7;
00138     x8 = j8;
00139     x9 = j9;
00140     x10 = j10;
00141     x11 = j11;
00142     x12 = j12;
00143     x13 = j13;
00144     x14 = j14;
00145     x15 = j15;
00146     for (i = 20;i > 0;i -= 2) {
00147       QUARTERROUND( x0, x4, x8,x12)
00148       QUARTERROUND( x1, x5, x9,x13)
00149       QUARTERROUND( x2, x6,x10,x14)
00150       QUARTERROUND( x3, x7,x11,x15)
00151       QUARTERROUND( x0, x5,x10,x15)
00152       QUARTERROUND( x1, x6,x11,x12)
00153       QUARTERROUND( x2, x7, x8,x13)
00154       QUARTERROUND( x3, x4, x9,x14)
00155     }
00156     x0 = PLUS(x0,j0);
00157     x1 = PLUS(x1,j1);
00158     x2 = PLUS(x2,j2);
00159     x3 = PLUS(x3,j3);
00160     x4 = PLUS(x4,j4);
00161     x5 = PLUS(x5,j5);
00162     x6 = PLUS(x6,j6);
00163     x7 = PLUS(x7,j7);
00164     x8 = PLUS(x8,j8);
00165     x9 = PLUS(x9,j9);
00166     x10 = PLUS(x10,j10);
00167     x11 = PLUS(x11,j11);
00168     x12 = PLUS(x12,j12);
00169     x13 = PLUS(x13,j13);
00170     x14 = PLUS(x14,j14);
00171     x15 = PLUS(x15,j15);
00172 
00173 #ifndef KEYSTREAM_ONLY
00174     x0 = XOR(x0,U8TO32_LITTLE(m + 0));
00175     x1 = XOR(x1,U8TO32_LITTLE(m + 4));
00176     x2 = XOR(x2,U8TO32_LITTLE(m + 8));
00177     x3 = XOR(x3,U8TO32_LITTLE(m + 12));
00178     x4 = XOR(x4,U8TO32_LITTLE(m + 16));
00179     x5 = XOR(x5,U8TO32_LITTLE(m + 20));
00180     x6 = XOR(x6,U8TO32_LITTLE(m + 24));
00181     x7 = XOR(x7,U8TO32_LITTLE(m + 28));
00182     x8 = XOR(x8,U8TO32_LITTLE(m + 32));
00183     x9 = XOR(x9,U8TO32_LITTLE(m + 36));
00184     x10 = XOR(x10,U8TO32_LITTLE(m + 40));
00185     x11 = XOR(x11,U8TO32_LITTLE(m + 44));
00186     x12 = XOR(x12,U8TO32_LITTLE(m + 48));
00187     x13 = XOR(x13,U8TO32_LITTLE(m + 52));
00188     x14 = XOR(x14,U8TO32_LITTLE(m + 56));
00189     x15 = XOR(x15,U8TO32_LITTLE(m + 60));
00190 #endif
00191 
00192     j12 = PLUSONE(j12);
00193     if (!j12) {
00194       j13 = PLUSONE(j13);
00195       /* stopping at 2^70 bytes per nonce is user's responsibility */
00196     }
00197 
00198     U32TO8_LITTLE(c + 0,x0);
00199     U32TO8_LITTLE(c + 4,x1);
00200     U32TO8_LITTLE(c + 8,x2);
00201     U32TO8_LITTLE(c + 12,x3);
00202     U32TO8_LITTLE(c + 16,x4);
00203     U32TO8_LITTLE(c + 20,x5);
00204     U32TO8_LITTLE(c + 24,x6);
00205     U32TO8_LITTLE(c + 28,x7);
00206     U32TO8_LITTLE(c + 32,x8);
00207     U32TO8_LITTLE(c + 36,x9);
00208     U32TO8_LITTLE(c + 40,x10);
00209     U32TO8_LITTLE(c + 44,x11);
00210     U32TO8_LITTLE(c + 48,x12);
00211     U32TO8_LITTLE(c + 52,x13);
00212     U32TO8_LITTLE(c + 56,x14);
00213     U32TO8_LITTLE(c + 60,x15);
00214 
00215     if (bytes <= 64) {
00216       if (bytes < 64) {
00217         for (i = 0;i < bytes;++i) ctarget[i] = c[i];
00218       }
00219       x->input[12] = j12;
00220       x->input[13] = j13;
00221       return;
00222     }
00223     bytes -= 64;
00224     c += 64;
00225 #ifndef KEYSTREAM_ONLY
00226     m += 64;
00227 #endif
00228   }
00229 }

Generated on Tue Apr 28 17:41:03 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha