19d12795Robert Mustacchi/*
29d12795Robert Mustacchichacha-merged.c version 20080118
39d12795Robert MustacchiD. J. Bernstein
49d12795Robert MustacchiPublic domain.
59d12795Robert Mustacchi*/
69d12795Robert Mustacchi
79d12795Robert Mustacchi/* $OpenBSD: chacha_private.h,v 1.2 2013/10/04 07:02:27 djm Exp $ */
89d12795Robert Mustacchi
99d12795Robert Mustacchi#include <chacha.h>
109d12795Robert Mustacchi#include <stddef.h>
119d12795Robert Mustacchi
129d12795Robert Mustacchitypedef unsigned char u8;
139d12795Robert Mustacchitypedef unsigned int u32;
149d12795Robert Mustacchitypedef unsigned int u_int;
159d12795Robert Mustacchi
169d12795Robert Mustacchi#define U8C(v) (v##U)
179d12795Robert Mustacchi#define U32C(v) (v##U)
189d12795Robert Mustacchi
199d12795Robert Mustacchi#define U8V(v) ((u8)(v) & U8C(0xFF))
209d12795Robert Mustacchi#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF))
219d12795Robert Mustacchi
229d12795Robert Mustacchi#define ROTL32(v, n) \
239d12795Robert Mustacchi  (U32V((v) << (n)) | ((v) >> (32 - (n))))
249d12795Robert Mustacchi
259d12795Robert Mustacchi#define U8TO32_LITTLE(p) \
269d12795Robert Mustacchi  (((u32)((p)[0])      ) | \
279d12795Robert Mustacchi   ((u32)((p)[1]) <<  8) | \
289d12795Robert Mustacchi   ((u32)((p)[2]) << 16) | \
299d12795Robert Mustacchi   ((u32)((p)[3]) << 24))
309d12795Robert Mustacchi
319d12795Robert Mustacchi#define U32TO8_LITTLE(p, v) \
329d12795Robert Mustacchi  do { \
339d12795Robert Mustacchi    (p)[0] = U8V((v)      ); \
349d12795Robert Mustacchi    (p)[1] = U8V((v) >>  8); \
359d12795Robert Mustacchi    (p)[2] = U8V((v) >> 16); \
369d12795Robert Mustacchi    (p)[3] = U8V((v) >> 24); \
379d12795Robert Mustacchi  } while (0)
389d12795Robert Mustacchi
399d12795Robert Mustacchi#define ROTATE(v,c) (ROTL32(v,c))
409d12795Robert Mustacchi#define XOR(v,w) ((v) ^ (w))
419d12795Robert Mustacchi#define PLUS(v,w) (U32V((v) + (w)))
429d12795Robert Mustacchi#define PLUSONE(v) (PLUS((v),1))
439d12795Robert Mustacchi
449d12795Robert Mustacchi#define QUARTERROUND(a,b,c,d) \
459d12795Robert Mustacchi  a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
469d12795Robert Mustacchi  c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
479d12795Robert Mustacchi  a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
489d12795Robert Mustacchi  c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
499d12795Robert Mustacchi
509d12795Robert Mustacchistatic const char sigma[16] = "expand 32-byte k";
519d12795Robert Mustacchistatic const char tau[16] = "expand 16-byte k";
529d12795Robert Mustacchi
539d12795Robert Mustacchivoid
549d12795Robert Mustacchichacha_keysetup(chacha_ctx_t *x,const u8 *k,u32 kbits,u32 ivbits)
559d12795Robert Mustacchi{
569d12795Robert Mustacchi  const char *constants;
579d12795Robert Mustacchi
589d12795Robert Mustacchi  x->chacha_input[4] = U8TO32_LITTLE(k + 0);
599d12795Robert Mustacchi  x->chacha_input[5] = U8TO32_LITTLE(k + 4);
609d12795Robert Mustacchi  x->chacha_input[6] = U8TO32_LITTLE(k + 8);
619d12795Robert Mustacchi  x->chacha_input[7] = U8TO32_LITTLE(k + 12);
629d12795Robert Mustacchi  if (kbits == 256) { /* recommended */
639d12795Robert Mustacchi    k += 16;
649d12795Robert Mustacchi    constants = sigma;
659d12795Robert Mustacchi  } else { /* kbits == 128 */
669d12795Robert Mustacchi    constants = tau;
679d12795Robert Mustacchi  }
689d12795Robert Mustacchi  x->chacha_input[8] = U8TO32_LITTLE(k + 0);
699d12795Robert Mustacchi  x->chacha_input[9] = U8TO32_LITTLE(k + 4);
709d12795Robert Mustacchi  x->chacha_input[10] = U8TO32_LITTLE(k + 8);
719d12795Robert Mustacchi  x->chacha_input[11] = U8TO32_LITTLE(k + 12);
729d12795Robert Mustacchi  x->chacha_input[0] = U8TO32_LITTLE(constants + 0);
739d12795Robert Mustacchi  x->chacha_input[1] = U8TO32_LITTLE(constants + 4);
749d12795Robert Mustacchi  x->chacha_input[2] = U8TO32_LITTLE(constants + 8);
759d12795Robert Mustacchi  x->chacha_input[3] = U8TO32_LITTLE(constants + 12);
769d12795Robert Mustacchi}
779d12795Robert Mustacchi
789d12795Robert Mustacchivoid
799d12795Robert Mustacchichacha_ivsetup(chacha_ctx_t *x,const u8 *iv)
809d12795Robert Mustacchi{
819d12795Robert Mustacchi  x->chacha_input[12] = 0;
829d12795Robert Mustacchi  x->chacha_input[13] = 0;
839d12795Robert Mustacchi  x->chacha_input[14] = U8TO32_LITTLE(iv + 0);
849d12795Robert Mustacchi  x->chacha_input[15] = U8TO32_LITTLE(iv + 4);
859d12795Robert Mustacchi}
869d12795Robert Mustacchi
879d12795Robert Mustacchivoid
889d12795Robert Mustacchichacha_encrypt_bytes(chacha_ctx_t *x,const u8 *m,u8 *c,u32 bytes)
899d12795Robert Mustacchi{
909d12795Robert Mustacchi  u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
919d12795Robert Mustacchi  u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
929d12795Robert Mustacchi  u8 *ctarget = NULL;
939d12795Robert Mustacchi  u8 tmp[64];
949d12795Robert Mustacchi  u_int i;
959d12795Robert Mustacchi
969d12795Robert Mustacchi  if (!bytes) return;
979d12795Robert Mustacchi
989d12795Robert Mustacchi  j0 = x->chacha_input[0];
999d12795Robert Mustacchi  j1 = x->chacha_input[1];
1009d12795Robert Mustacchi  j2 = x->chacha_input[2];
1019d12795Robert Mustacchi  j3 = x->chacha_input[3];
1029d12795Robert Mustacchi  j4 = x->chacha_input[4];
1039d12795Robert Mustacchi  j5 = x->chacha_input[5];
1049d12795Robert Mustacchi  j6 = x->chacha_input[6];
1059d12795Robert Mustacchi  j7 = x->chacha_input[7];
1069d12795Robert Mustacchi  j8 = x->chacha_input[8];
1079d12795Robert Mustacchi  j9 = x->chacha_input[9];
1089d12795Robert Mustacchi  j10 = x->chacha_input[10];
1099d12795Robert Mustacchi  j11 = x->chacha_input[11];
1109d12795Robert Mustacchi  j12 = x->chacha_input[12];
1119d12795Robert Mustacchi  j13 = x->chacha_input[13];
1129d12795Robert Mustacchi  j14 = x->chacha_input[14];
1139d12795Robert Mustacchi  j15 = x->chacha_input[15];
1149d12795Robert Mustacchi
1159d12795Robert Mustacchi  for (;;) {
1169d12795Robert Mustacchi    if (bytes < 64) {
1179d12795Robert Mustacchi      for (i = 0;i < bytes;++i) tmp[i] = m[i];
1189d12795Robert Mustacchi      m = tmp;
1199d12795Robert Mustacchi      ctarget = c;
1209d12795Robert Mustacchi      c = tmp;
1219d12795Robert Mustacchi    }
1229d12795Robert Mustacchi    x0 = j0;
1239d12795Robert Mustacchi    x1 = j1;
1249d12795Robert Mustacchi    x2 = j2;
1259d12795Robert Mustacchi    x3 = j3;
1269d12795Robert Mustacchi    x4 = j4;
1279d12795Robert Mustacchi    x5 = j5;
1289d12795Robert Mustacchi    x6 = j6;
1299d12795Robert Mustacchi    x7 = j7;
1309d12795Robert Mustacchi    x8 = j8;
1319d12795Robert Mustacchi    x9 = j9;
1329d12795Robert Mustacchi    x10 = j10;
1339d12795Robert Mustacchi    x11 = j11;
1349d12795Robert Mustacchi    x12 = j12;
1359d12795Robert Mustacchi    x13 = j13;
1369d12795Robert Mustacchi    x14 = j14;
1379d12795Robert Mustacchi    x15 = j15;
1389d12795Robert Mustacchi    for (i = 20;i > 0;i -= 2) {
1399d12795Robert Mustacchi      QUARTERROUND( x0, x4, x8,x12)
1409d12795Robert Mustacchi      QUARTERROUND( x1, x5, x9,x13)
1419d12795Robert Mustacchi      QUARTERROUND( x2, x6,x10,x14)
1429d12795Robert Mustacchi      QUARTERROUND( x3, x7,x11,x15)
1439d12795Robert Mustacchi      QUARTERROUND( x0, x5,x10,x15)
1449d12795Robert Mustacchi      QUARTERROUND( x1, x6,x11,x12)
1459d12795Robert Mustacchi      QUARTERROUND( x2, x7, x8,x13)
1469d12795Robert Mustacchi      QUARTERROUND( x3, x4, x9,x14)
1479d12795Robert Mustacchi    }
1489d12795Robert Mustacchi    x0 = PLUS(x0,j0);
1499d12795Robert Mustacchi    x1 = PLUS(x1,j1);
1509d12795Robert Mustacchi    x2 = PLUS(x2,j2);
1519d12795Robert Mustacchi    x3 = PLUS(x3,j3);
1529d12795Robert Mustacchi    x4 = PLUS(x4,j4);
1539d12795Robert Mustacchi    x5 = PLUS(x5,j5);
1549d12795Robert Mustacchi    x6 = PLUS(x6,j6);
1559d12795Robert Mustacchi    x7 = PLUS(x7,j7);
1569d12795Robert Mustacchi    x8 = PLUS(x8,j8);
1579d12795Robert Mustacchi    x9 = PLUS(x9,j9);
1589d12795Robert Mustacchi    x10 = PLUS(x10,j10);
1599d12795Robert Mustacchi    x11 = PLUS(x11,j11);
1609d12795Robert Mustacchi    x12 = PLUS(x12,j12);
1619d12795Robert Mustacchi    x13 = PLUS(x13,j13);
1629d12795Robert Mustacchi    x14 = PLUS(x14,j14);
1639d12795Robert Mustacchi    x15 = PLUS(x15,j15);
1649d12795Robert Mustacchi
1659d12795Robert Mustacchi#ifndef KEYSTREAM_ONLY
1669d12795Robert Mustacchi    x0 = XOR(x0,U8TO32_LITTLE(m + 0));
1679d12795Robert Mustacchi    x1 = XOR(x1,U8TO32_LITTLE(m + 4));
1689d12795Robert Mustacchi    x2 = XOR(x2,U8TO32_LITTLE(m + 8));
1699d12795Robert Mustacchi    x3 = XOR(x3,U8TO32_LITTLE(m + 12));
1709d12795Robert Mustacchi    x4 = XOR(x4,U8TO32_LITTLE(m + 16));
1719d12795Robert Mustacchi    x5 = XOR(x5,U8TO32_LITTLE(m + 20));
1729d12795Robert Mustacchi    x6 = XOR(x6,U8TO32_LITTLE(m + 24));
1739d12795Robert Mustacchi    x7 = XOR(x7,U8TO32_LITTLE(m + 28));
1749d12795Robert Mustacchi    x8 = XOR(x8,U8TO32_LITTLE(m + 32));
1759d12795Robert Mustacchi    x9 = XOR(x9,U8TO32_LITTLE(m + 36));
1769d12795Robert Mustacchi    x10 = XOR(x10,U8TO32_LITTLE(m + 40));
1779d12795Robert Mustacchi    x11 = XOR(x11,U8TO32_LITTLE(m + 44));
1789d12795Robert Mustacchi    x12 = XOR(x12,U8TO32_LITTLE(m + 48));
1799d12795Robert Mustacchi    x13 = XOR(x13,U8TO32_LITTLE(m + 52));
1809d12795Robert Mustacchi    x14 = XOR(x14,U8TO32_LITTLE(m + 56));
1819d12795Robert Mustacchi    x15 = XOR(x15,U8TO32_LITTLE(m + 60));
1829d12795Robert Mustacchi#endif
1839d12795Robert Mustacchi
1849d12795Robert Mustacchi    j12 = PLUSONE(j12);
1859d12795Robert Mustacchi    if (!j12) {
1869d12795Robert Mustacchi      j13 = PLUSONE(j13);
1879d12795Robert Mustacchi      /* stopping at 2^70 bytes per nonce is user's responsibility */
1889d12795Robert Mustacchi    }
1899d12795Robert Mustacchi
1909d12795Robert Mustacchi    U32TO8_LITTLE(c + 0,x0);
1919d12795Robert Mustacchi    U32TO8_LITTLE(c + 4,x1);
1929d12795Robert Mustacchi    U32TO8_LITTLE(c + 8,x2);
1939d12795Robert Mustacchi    U32TO8_LITTLE(c + 12,x3);
1949d12795Robert Mustacchi    U32TO8_LITTLE(c + 16,x4);
1959d12795Robert Mustacchi    U32TO8_LITTLE(c + 20,x5);
1969d12795Robert Mustacchi    U32TO8_LITTLE(c + 24,x6);
1979d12795Robert Mustacchi    U32TO8_LITTLE(c + 28,x7);
1989d12795Robert Mustacchi    U32TO8_LITTLE(c + 32,x8);
1999d12795Robert Mustacchi    U32TO8_LITTLE(c + 36,x9);
2009d12795Robert Mustacchi    U32TO8_LITTLE(c + 40,x10);
2019d12795Robert Mustacchi    U32TO8_LITTLE(c + 44,x11);
2029d12795Robert Mustacchi    U32TO8_LITTLE(c + 48,x12);
2039d12795Robert Mustacchi    U32TO8_LITTLE(c + 52,x13);
2049d12795Robert Mustacchi    U32TO8_LITTLE(c + 56,x14);
2059d12795Robert Mustacchi    U32TO8_LITTLE(c + 60,x15);
2069d12795Robert Mustacchi
2079d12795Robert Mustacchi    if (bytes <= 64) {
2089d12795Robert Mustacchi      if (bytes < 64) {
2099d12795Robert Mustacchi        for (i = 0;i < bytes;++i) ctarget[i] = c[i];
2109d12795Robert Mustacchi      }
2119d12795Robert Mustacchi      x->chacha_input[12] = j12;
2129d12795Robert Mustacchi      x->chacha_input[13] = j13;
2139d12795Robert Mustacchi      return;
2149d12795Robert Mustacchi    }
2159d12795Robert Mustacchi    bytes -= 64;
2169d12795Robert Mustacchi    c += 64;
2179d12795Robert Mustacchi#ifndef KEYSTREAM_ONLY
2189d12795Robert Mustacchi    m += 64;
2199d12795Robert Mustacchi#endif
2209d12795Robert Mustacchi  }
2219d12795Robert Mustacchi}
222