00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 typedef unsigned char u8;
00013 typedef unsigned int u32;
00014
00015 typedef struct
00016 {
00017 u32 input[16];
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) {
00071 k += 16;
00072 constants = sigma;
00073 } else {
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
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 }