Home | History | Annotate | Line # | Download | only in dist
      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