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