1 /* 2 chacha-merged.c version 20080118 3 D. J. Bernstein 4 Public domain. 5 */ 6 7 /* $OpenBSD: chacha.c,v 1.1 2013/11/21 00:45:44 djm Exp $ */ 8 9 #include <sys/cdefs.h> 10 #include <sys/param.h> 11 #include <sys/types.h> 12 13 #include <crypto/chacha20/chacha.h> 14 15 typedef uint8_t u8; 16 typedef uint32_t u32; 17 18 typedef struct chacha_ctx chacha_ctx; 19 20 #define U8C(v) (v##U) 21 #define U32C(v) (v##U) 22 23 #define U8V(v) ((u8)(v) & U8C(0xFF)) 24 #define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF)) 25 26 #define ROTL32(v, n) \ 27 (U32V((v) << (n)) | ((v) >> (32 - (n)))) 28 29 #define U8TO32_LITTLE(p) \ 30 (((u32)((p)[0]) ) | \ 31 ((u32)((p)[1]) << 8) | \ 32 ((u32)((p)[2]) << 16) | \ 33 ((u32)((p)[3]) << 24)) 34 35 #define U32TO8_LITTLE(p, v) \ 36 do { \ 37 (p)[0] = U8V((v) ); \ 38 (p)[1] = U8V((v) >> 8); \ 39 (p)[2] = U8V((v) >> 16); \ 40 (p)[3] = U8V((v) >> 24); \ 41 } while (0) 42 43 #define ROTATE(v,c) (ROTL32(v,c)) 44 #define XOR(v,w) ((v) ^ (w)) 45 #define PLUS(v,w) (U32V((v) + (w))) 46 #define PLUSONE(v) (PLUS((v),1)) 47 48 #define QUARTERROUND(a,b,c,d) \ 49 a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ 50 c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ 51 a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ 52 c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); 53 54 static const char sigma[16] = "expand 32-byte k"; 55 static const char tau[16] = "expand 16-byte k"; 56 57 LOCAL void 58 chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits) 59 { 60 const char *constants; 61 62 x->input[4] = U8TO32_LITTLE(k + 0); 63 x->input[5] = U8TO32_LITTLE(k + 4); 64 x->input[6] = U8TO32_LITTLE(k + 8); 65 x->input[7] = U8TO32_LITTLE(k + 12); 66 if (kbits == 256) { /* recommended */ 67 k += 16; 68 constants = sigma; 69 } else { /* kbits == 128 */ 70 constants = tau; 71 } 72 x->input[8] = U8TO32_LITTLE(k + 0); 73 x->input[9] = U8TO32_LITTLE(k + 4); 74 x->input[10] = U8TO32_LITTLE(k + 8); 75 x->input[11] = U8TO32_LITTLE(k + 12); 76 x->input[0] = U8TO32_LITTLE(constants + 0); 77 x->input[1] = U8TO32_LITTLE(constants + 4); 78 x->input[2] = U8TO32_LITTLE(constants + 8); 79 x->input[3] = U8TO32_LITTLE(constants + 12); 80 } 81 82 LOCAL void 83 chacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter) 84 { 85 #ifndef CHACHA_NONCE0_CTR128 86 x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0); 87 x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4); 88 x->input[14] = U8TO32_LITTLE(iv + 0); 89 x->input[15] = U8TO32_LITTLE(iv + 4); 90 #else 91 // CHACHA_STATELEN 92 (void)iv; 93 x->input[12] = U8TO32_LITTLE(counter + 0); 94 x->input[13] = U8TO32_LITTLE(counter + 4); 95 x->input[14] = U8TO32_LITTLE(counter + 8); 96 x->input[15] = U8TO32_LITTLE(counter + 12); 97 #endif 98 } 99 100 #ifdef CHACHA_NONCE0_CTR128 101 LOCAL void 102 chacha_ctrsave(const chacha_ctx *x, u8 *counter) 103 { 104 U32TO8_LITTLE(counter + 0, x->input[12]); 105 U32TO8_LITTLE(counter + 4, x->input[13]); 106 U32TO8_LITTLE(counter + 8, x->input[14]); 107 U32TO8_LITTLE(counter + 12, x->input[15]); 108 } 109 #endif 110 111 LOCAL void 112 chacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes) 113 { 114 u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; 115 u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; 116 u8 *ctarget = NULL; 117 u8 tmp[64]; 118 u_int i; 119 120 if (!bytes) return; 121 122 j0 = x->input[0]; 123 j1 = x->input[1]; 124 j2 = x->input[2]; 125 j3 = x->input[3]; 126 j4 = x->input[4]; 127 j5 = x->input[5]; 128 j6 = x->input[6]; 129 j7 = x->input[7]; 130 j8 = x->input[8]; 131 j9 = x->input[9]; 132 j10 = x->input[10]; 133 j11 = x->input[11]; 134 j12 = x->input[12]; 135 j13 = x->input[13]; 136 j14 = x->input[14]; 137 j15 = x->input[15]; 138 139 for (;;) { 140 if (bytes < 64) { 141 #ifndef KEYSTREAM_ONLY 142 for (i = 0;i < bytes;++i) tmp[i] = m[i]; 143 m = tmp; 144 #endif 145 ctarget = c; 146 c = tmp; 147 } 148 x0 = j0; 149 x1 = j1; 150 x2 = j2; 151 x3 = j3; 152 x4 = j4; 153 x5 = j5; 154 x6 = j6; 155 x7 = j7; 156 x8 = j8; 157 x9 = j9; 158 x10 = j10; 159 x11 = j11; 160 x12 = j12; 161 x13 = j13; 162 x14 = j14; 163 x15 = j15; 164 for (i = 20;i > 0;i -= 2) { 165 QUARTERROUND( x0, x4, x8,x12) 166 QUARTERROUND( x1, x5, x9,x13) 167 QUARTERROUND( x2, x6,x10,x14) 168 QUARTERROUND( x3, x7,x11,x15) 169 QUARTERROUND( x0, x5,x10,x15) 170 QUARTERROUND( x1, x6,x11,x12) 171 QUARTERROUND( x2, x7, x8,x13) 172 QUARTERROUND( x3, x4, x9,x14) 173 } 174 x0 = PLUS(x0,j0); 175 x1 = PLUS(x1,j1); 176 x2 = PLUS(x2,j2); 177 x3 = PLUS(x3,j3); 178 x4 = PLUS(x4,j4); 179 x5 = PLUS(x5,j5); 180 x6 = PLUS(x6,j6); 181 x7 = PLUS(x7,j7); 182 x8 = PLUS(x8,j8); 183 x9 = PLUS(x9,j9); 184 x10 = PLUS(x10,j10); 185 x11 = PLUS(x11,j11); 186 x12 = PLUS(x12,j12); 187 x13 = PLUS(x13,j13); 188 x14 = PLUS(x14,j14); 189 x15 = PLUS(x15,j15); 190 191 #ifndef KEYSTREAM_ONLY 192 x0 = XOR(x0,U8TO32_LITTLE(m + 0)); 193 x1 = XOR(x1,U8TO32_LITTLE(m + 4)); 194 x2 = XOR(x2,U8TO32_LITTLE(m + 8)); 195 x3 = XOR(x3,U8TO32_LITTLE(m + 12)); 196 x4 = XOR(x4,U8TO32_LITTLE(m + 16)); 197 x5 = XOR(x5,U8TO32_LITTLE(m + 20)); 198 x6 = XOR(x6,U8TO32_LITTLE(m + 24)); 199 x7 = XOR(x7,U8TO32_LITTLE(m + 28)); 200 x8 = XOR(x8,U8TO32_LITTLE(m + 32)); 201 x9 = XOR(x9,U8TO32_LITTLE(m + 36)); 202 x10 = XOR(x10,U8TO32_LITTLE(m + 40)); 203 x11 = XOR(x11,U8TO32_LITTLE(m + 44)); 204 x12 = XOR(x12,U8TO32_LITTLE(m + 48)); 205 x13 = XOR(x13,U8TO32_LITTLE(m + 52)); 206 x14 = XOR(x14,U8TO32_LITTLE(m + 56)); 207 x15 = XOR(x15,U8TO32_LITTLE(m + 60)); 208 #endif 209 210 j12 = PLUSONE(j12); 211 if (!j12) { 212 j13 = PLUSONE(j13); 213 #ifndef CHACHA_NONCE0_CTR128 214 /* stopping at 2^70 bytes per nonce is user's responsibility */ 215 #else 216 if (!j13) { 217 j14 = PLUSONE(j14); 218 if (!j14) { 219 j15 = PLUSONE(j15); 220 } 221 } 222 #endif 223 } 224 225 U32TO8_LITTLE(c + 0,x0); 226 U32TO8_LITTLE(c + 4,x1); 227 U32TO8_LITTLE(c + 8,x2); 228 U32TO8_LITTLE(c + 12,x3); 229 U32TO8_LITTLE(c + 16,x4); 230 U32TO8_LITTLE(c + 20,x5); 231 U32TO8_LITTLE(c + 24,x6); 232 U32TO8_LITTLE(c + 28,x7); 233 U32TO8_LITTLE(c + 32,x8); 234 U32TO8_LITTLE(c + 36,x9); 235 U32TO8_LITTLE(c + 40,x10); 236 U32TO8_LITTLE(c + 44,x11); 237 U32TO8_LITTLE(c + 48,x12); 238 U32TO8_LITTLE(c + 52,x13); 239 U32TO8_LITTLE(c + 56,x14); 240 U32TO8_LITTLE(c + 60,x15); 241 242 if (bytes <= 64) { 243 if (bytes < 64) { 244 for (i = 0;i < bytes;++i) ctarget[i] = c[i]; 245 } 246 x->input[12] = j12; 247 x->input[13] = j13; 248 #ifdef CHACHA_NONCE0_CTR128 249 x->input[14] = j14; 250 x->input[15] = j15; 251 #endif 252 return; 253 } 254 bytes -= 64; 255 c += 64; 256 #ifndef KEYSTREAM_ONLY 257 m += 64; 258 #endif 259 } 260 } 261