Blame src/external/chacha.c

Packit Service 31306d
/*
Packit Service 31306d
chacha-merged.c version 20080118
Packit Service 31306d
D. J. Bernstein
Packit Service 31306d
Public domain.
Packit Service 31306d
 */
Packit Service 31306d
Packit Service 31306d
#include <stdint.h>
Packit Service 31306d
#include <stddef.h>
Packit Service 31306d
#include <sys/types.h>
Packit Service 31306d
Packit Service 31306d
#include "libssh/chacha.h"
Packit Service 31306d
Packit Service 31306d
typedef struct chacha_ctx chacha_ctx;
Packit Service 31306d
Packit Service 31306d
#define U8C(v) (v##U)
Packit Service 31306d
#define U32C(v) (v##U)
Packit Service 31306d
Packit Service 31306d
#define U8V(v) ((uint8_t)(v) & U8C(0xFF))
Packit Service 31306d
#define U32V(v) ((uint32_t)(v) & U32C(0xFFFFFFFF))
Packit Service 31306d
Packit Service 31306d
#define ROTL32(v, n) \
Packit Service 31306d
        (U32V((v) << (n)) | ((v) >> (32 - (n))))
Packit Service 31306d
Packit Service 31306d
#define U8TO32_LITTLE(p) \
Packit Service 31306d
        (((uint32_t)((p)[0])      ) | \
Packit Service 31306d
         ((uint32_t)((p)[1]) <<  8) | \
Packit Service 31306d
         ((uint32_t)((p)[2]) << 16) | \
Packit Service 31306d
         ((uint32_t)((p)[3]) << 24))
Packit Service 31306d
Packit Service 31306d
#define U32TO8_LITTLE(p, v) \
Packit Service 31306d
        do { \
Packit Service 31306d
            (p)[0] = U8V((v)      ); \
Packit Service 31306d
            (p)[1] = U8V((v) >>  8); \
Packit Service 31306d
            (p)[2] = U8V((v) >> 16); \
Packit Service 31306d
            (p)[3] = U8V((v) >> 24); \
Packit Service 31306d
        } while (0)
Packit Service 31306d
Packit Service 31306d
#define ROTATE(v,c) (ROTL32(v,c))
Packit Service 31306d
#define XOR(v,w) ((v) ^ (w))
Packit Service 31306d
#define PLUS(v,w) (U32V((v) + (w)))
Packit Service 31306d
#define PLUSONE(v) (PLUS((v),1))
Packit Service 31306d
Packit Service 31306d
#define QUARTERROUND(a,b,c,d) \
Packit Service 31306d
        a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
Packit Service 31306d
        c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
Packit Service 31306d
        a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
Packit Service 31306d
        c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
Packit Service 31306d
Packit Service 31306d
static const char sigma[16] = "expand 32-byte k";
Packit Service 31306d
static const char tau[16] = "expand 16-byte k";
Packit Service 31306d
Packit Service 31306d
void
Packit Service 31306d
chacha_keysetup(chacha_ctx *x,const uint8_t *k,uint32_t kbits)
Packit Service 31306d
{
Packit Service 31306d
    const char *constants;
Packit Service 31306d
Packit Service 31306d
    x->input[4] = U8TO32_LITTLE(k + 0);
Packit Service 31306d
    x->input[5] = U8TO32_LITTLE(k + 4);
Packit Service 31306d
    x->input[6] = U8TO32_LITTLE(k + 8);
Packit Service 31306d
    x->input[7] = U8TO32_LITTLE(k + 12);
Packit Service 31306d
    if (kbits == 256) { /* recommended */
Packit Service 31306d
        k += 16;
Packit Service 31306d
        constants = sigma;
Packit Service 31306d
    } else { /* kbits == 128 */
Packit Service 31306d
        constants = tau;
Packit Service 31306d
    }
Packit Service 31306d
    x->input[8] = U8TO32_LITTLE(k + 0);
Packit Service 31306d
    x->input[9] = U8TO32_LITTLE(k + 4);
Packit Service 31306d
    x->input[10] = U8TO32_LITTLE(k + 8);
Packit Service 31306d
    x->input[11] = U8TO32_LITTLE(k + 12);
Packit Service 31306d
    x->input[0] = U8TO32_LITTLE(constants + 0);
Packit Service 31306d
    x->input[1] = U8TO32_LITTLE(constants + 4);
Packit Service 31306d
    x->input[2] = U8TO32_LITTLE(constants + 8);
Packit Service 31306d
    x->input[3] = U8TO32_LITTLE(constants + 12);
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
void
Packit Service 31306d
chacha_ivsetup(chacha_ctx *x, const uint8_t *iv, const uint8_t *counter)
Packit Service 31306d
{
Packit Service 31306d
    x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
Packit Service 31306d
    x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4);
Packit Service 31306d
    x->input[14] = U8TO32_LITTLE(iv + 0);
Packit Service 31306d
    x->input[15] = U8TO32_LITTLE(iv + 4);
Packit Service 31306d
}
Packit Service 31306d
Packit Service 31306d
void
Packit Service 31306d
chacha_encrypt_bytes(chacha_ctx *x,const uint8_t *m,uint8_t *c,uint32_t bytes)
Packit Service 31306d
{
Packit Service 31306d
    uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
Packit Service 31306d
    uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
Packit Service 31306d
    uint8_t *ctarget = NULL;
Packit Service 31306d
    uint8_t tmp[64];
Packit Service 31306d
    uint32_t i;
Packit Service 31306d
Packit Service 31306d
    if (!bytes) return;
Packit Service 31306d
Packit Service 31306d
    j0 = x->input[0];
Packit Service 31306d
    j1 = x->input[1];
Packit Service 31306d
    j2 = x->input[2];
Packit Service 31306d
    j3 = x->input[3];
Packit Service 31306d
    j4 = x->input[4];
Packit Service 31306d
    j5 = x->input[5];
Packit Service 31306d
    j6 = x->input[6];
Packit Service 31306d
    j7 = x->input[7];
Packit Service 31306d
    j8 = x->input[8];
Packit Service 31306d
    j9 = x->input[9];
Packit Service 31306d
    j10 = x->input[10];
Packit Service 31306d
    j11 = x->input[11];
Packit Service 31306d
    j12 = x->input[12];
Packit Service 31306d
    j13 = x->input[13];
Packit Service 31306d
    j14 = x->input[14];
Packit Service 31306d
    j15 = x->input[15];
Packit Service 31306d
Packit Service 31306d
    for (;;) {
Packit Service 31306d
        if (bytes < 64) {
Packit Service 31306d
            for (i = 0;i < bytes;++i) tmp[i] = m[i];
Packit Service 31306d
            m = tmp;
Packit Service 31306d
            ctarget = c;
Packit Service 31306d
            c = tmp;
Packit Service 31306d
        }
Packit Service 31306d
        x0 = j0;
Packit Service 31306d
        x1 = j1;
Packit Service 31306d
        x2 = j2;
Packit Service 31306d
        x3 = j3;
Packit Service 31306d
        x4 = j4;
Packit Service 31306d
        x5 = j5;
Packit Service 31306d
        x6 = j6;
Packit Service 31306d
        x7 = j7;
Packit Service 31306d
        x8 = j8;
Packit Service 31306d
        x9 = j9;
Packit Service 31306d
        x10 = j10;
Packit Service 31306d
        x11 = j11;
Packit Service 31306d
        x12 = j12;
Packit Service 31306d
        x13 = j13;
Packit Service 31306d
        x14 = j14;
Packit Service 31306d
        x15 = j15;
Packit Service 31306d
        for (i = 20;i > 0;i -= 2) {
Packit Service 31306d
            QUARTERROUND( x0, x4, x8,x12)
Packit Service 31306d
                      QUARTERROUND( x1, x5, x9,x13)
Packit Service 31306d
                      QUARTERROUND( x2, x6,x10,x14)
Packit Service 31306d
                      QUARTERROUND( x3, x7,x11,x15)
Packit Service 31306d
                      QUARTERROUND( x0, x5,x10,x15)
Packit Service 31306d
                      QUARTERROUND( x1, x6,x11,x12)
Packit Service 31306d
                      QUARTERROUND( x2, x7, x8,x13)
Packit Service 31306d
                      QUARTERROUND( x3, x4, x9,x14)
Packit Service 31306d
        }
Packit Service 31306d
        x0 = PLUS(x0,j0);
Packit Service 31306d
        x1 = PLUS(x1,j1);
Packit Service 31306d
        x2 = PLUS(x2,j2);
Packit Service 31306d
        x3 = PLUS(x3,j3);
Packit Service 31306d
        x4 = PLUS(x4,j4);
Packit Service 31306d
        x5 = PLUS(x5,j5);
Packit Service 31306d
        x6 = PLUS(x6,j6);
Packit Service 31306d
        x7 = PLUS(x7,j7);
Packit Service 31306d
        x8 = PLUS(x8,j8);
Packit Service 31306d
        x9 = PLUS(x9,j9);
Packit Service 31306d
        x10 = PLUS(x10,j10);
Packit Service 31306d
        x11 = PLUS(x11,j11);
Packit Service 31306d
        x12 = PLUS(x12,j12);
Packit Service 31306d
        x13 = PLUS(x13,j13);
Packit Service 31306d
        x14 = PLUS(x14,j14);
Packit Service 31306d
        x15 = PLUS(x15,j15);
Packit Service 31306d
Packit Service 31306d
        x0 = XOR(x0,U8TO32_LITTLE(m + 0));
Packit Service 31306d
        x1 = XOR(x1,U8TO32_LITTLE(m + 4));
Packit Service 31306d
        x2 = XOR(x2,U8TO32_LITTLE(m + 8));
Packit Service 31306d
        x3 = XOR(x3,U8TO32_LITTLE(m + 12));
Packit Service 31306d
        x4 = XOR(x4,U8TO32_LITTLE(m + 16));
Packit Service 31306d
        x5 = XOR(x5,U8TO32_LITTLE(m + 20));
Packit Service 31306d
        x6 = XOR(x6,U8TO32_LITTLE(m + 24));
Packit Service 31306d
        x7 = XOR(x7,U8TO32_LITTLE(m + 28));
Packit Service 31306d
        x8 = XOR(x8,U8TO32_LITTLE(m + 32));
Packit Service 31306d
        x9 = XOR(x9,U8TO32_LITTLE(m + 36));
Packit Service 31306d
        x10 = XOR(x10,U8TO32_LITTLE(m + 40));
Packit Service 31306d
        x11 = XOR(x11,U8TO32_LITTLE(m + 44));
Packit Service 31306d
        x12 = XOR(x12,U8TO32_LITTLE(m + 48));
Packit Service 31306d
        x13 = XOR(x13,U8TO32_LITTLE(m + 52));
Packit Service 31306d
        x14 = XOR(x14,U8TO32_LITTLE(m + 56));
Packit Service 31306d
        x15 = XOR(x15,U8TO32_LITTLE(m + 60));
Packit Service 31306d
Packit Service 31306d
        j12 = PLUSONE(j12);
Packit Service 31306d
        if (!j12) {
Packit Service 31306d
            j13 = PLUSONE(j13);
Packit Service 31306d
            /* stopping at 2^70 bytes per nonce is user's responsibility */
Packit Service 31306d
        }
Packit Service 31306d
Packit Service 31306d
        U32TO8_LITTLE(c + 0,x0);
Packit Service 31306d
        U32TO8_LITTLE(c + 4,x1);
Packit Service 31306d
        U32TO8_LITTLE(c + 8,x2);
Packit Service 31306d
        U32TO8_LITTLE(c + 12,x3);
Packit Service 31306d
        U32TO8_LITTLE(c + 16,x4);
Packit Service 31306d
        U32TO8_LITTLE(c + 20,x5);
Packit Service 31306d
        U32TO8_LITTLE(c + 24,x6);
Packit Service 31306d
        U32TO8_LITTLE(c + 28,x7);
Packit Service 31306d
        U32TO8_LITTLE(c + 32,x8);
Packit Service 31306d
        U32TO8_LITTLE(c + 36,x9);
Packit Service 31306d
        U32TO8_LITTLE(c + 40,x10);
Packit Service 31306d
        U32TO8_LITTLE(c + 44,x11);
Packit Service 31306d
        U32TO8_LITTLE(c + 48,x12);
Packit Service 31306d
        U32TO8_LITTLE(c + 52,x13);
Packit Service 31306d
        U32TO8_LITTLE(c + 56,x14);
Packit Service 31306d
        U32TO8_LITTLE(c + 60,x15);
Packit Service 31306d
Packit Service 31306d
        if (bytes <= 64) {
Packit Service 31306d
            if (bytes < 64) {
Packit Service 31306d
                for (i = 0;i < bytes;++i) ctarget[i] = c[i];
Packit Service 31306d
            }
Packit Service 31306d
            x->input[12] = j12;
Packit Service 31306d
            x->input[13] = j13;
Packit Service 31306d
            return;
Packit Service 31306d
        }
Packit Service 31306d
        bytes -= 64;
Packit Service 31306d
        c += 64;
Packit Service 31306d
        m += 64;
Packit Service 31306d
    }
Packit Service 31306d
}