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