/*
 * Copyright 2017, DornerWorks
 *
 * SPDX-License-Identifier: GPL-2.0-only
 *
 * This data was produced by DornerWorks, Ltd. of Grand Rapids, MI, USA under
 * a DARPA SBIR, Contract Number D16PC00107.
 *
 * Approved for Public Release, Distribution Unlimited.
 *
 */

/*
 * public domain sha256 crypt implementation
 *
 * original sha crypt design: http://people.redhat.com/drepper/SHA-crypt.txt
 * in this implementation at least 32bit int is assumed,
 * key length is limited, the $5$ prefix is mandatory, '\n' and ':' is rejected
 * in the salt and rounds= setting must contain a valid iteration count,
 * on error "*" is returned.
 */
#include <printf.h>
#include <types.h>
#include <strops.h>

#include "../crypt_sha256.h"

#define KEY_MAX 256
#define SALT_MAX 16
#define ROUNDS_DEFAULT 5000
#define ROUNDS_MIN 1000
#define ROUNDS_MAX 9999999

/* public domain sha256 implementation based on fips180-3 */

static uint32_t ror(uint32_t n, int k)
{
    return (n >> k) | (n << (32 - k));
}
#define Ch(x,y,z)  (z ^ (x & (y ^ z)))
#define Maj(x,y,z) ((x & y) | (z & (x | y)))
#define S0(x)      (ror(x,2) ^ ror(x,13) ^ ror(x,22))
#define S1(x)      (ror(x,6) ^ ror(x,11) ^ ror(x,25))
#define R0(x)      (ror(x,7) ^ ror(x,18) ^ (x>>3))
#define R1(x)      (ror(x,17) ^ ror(x,19) ^ (x>>10))

static const uint32_t K[64] = {
    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};

static void processblock(sha256_t *s, const uint8_t *buf)
{
    uint32_t W[64], t1, t2, a, b, c, d, e, f, g, h;
    int i;

    for (i = 0; i < 16; i++) {
        W[i] = (uint32_t)buf[4 * i] << 24;
        W[i] |= (uint32_t)buf[4 * i + 1] << 16;
        W[i] |= (uint32_t)buf[4 * i + 2] << 8;
        W[i] |= buf[4 * i + 3];
    }
    for (; i < 64; i++) {
        W[i] = R1(W[i - 2]) + W[i - 7] + R0(W[i - 15]) + W[i - 16];
    }
    a = s->h[0];
    b = s->h[1];
    c = s->h[2];
    d = s->h[3];
    e = s->h[4];
    f = s->h[5];
    g = s->h[6];
    h = s->h[7];
    for (i = 0; i < 64; i++) {
        t1 = h + S1(e) + Ch(e, f, g) + K[i] + W[i];
        t2 = S0(a) + Maj(a, b, c);
        h = g;
        g = f;
        f = e;
        e = d + t1;
        d = c;
        c = b;
        b = a;
        a = t1 + t2;
    }
    s->h[0] += a;
    s->h[1] += b;
    s->h[2] += c;
    s->h[3] += d;
    s->h[4] += e;
    s->h[5] += f;
    s->h[6] += g;
    s->h[7] += h;
}

static void pad(sha256_t *s)
{
    unsigned r = s->len % 64;

    s->buf[r++] = 0x80;
    if (r > 56) {
        memset(s->buf + r, 0, 64 - r);
        r = 0;
        processblock(s, s->buf);
    }
    memset(s->buf + r, 0, 56 - r);
    s->len *= 8;
    s->buf[56] = s->len >> 56;
    s->buf[57] = s->len >> 48;
    s->buf[58] = s->len >> 40;
    s->buf[59] = s->len >> 32;
    s->buf[60] = s->len >> 24;
    s->buf[61] = s->len >> 16;
    s->buf[62] = s->len >> 8;
    s->buf[63] = s->len;
    processblock(s, s->buf);
}

void sha256_init(sha256_t *s)
{
    s->len = 0;
    s->h[0] = 0x6a09e667;
    s->h[1] = 0xbb67ae85;
    s->h[2] = 0x3c6ef372;
    s->h[3] = 0xa54ff53a;
    s->h[4] = 0x510e527f;
    s->h[5] = 0x9b05688c;
    s->h[6] = 0x1f83d9ab;
    s->h[7] = 0x5be0cd19;
}

void sha256_sum(sha256_t *s, uint8_t *md)
{
    int i;

    pad(s);
    for (i = 0; i < 8; i++) {
        md[4 * i] = s->h[i] >> 24;
        md[4 * i + 1] = s->h[i] >> 16;
        md[4 * i + 2] = s->h[i] >> 8;
        md[4 * i + 3] = s->h[i];
    }
}

void sha256_update(sha256_t *s, const void *m, unsigned long len)
{
    const uint8_t *p = m;
    unsigned r = s->len % 64;

    s->len += len;
    if (r) {
        if (len < 64 - r) {
            memcpy(s->buf + r, p, len);
            return;
        }
        memcpy(s->buf + r, p, 64 - r);
        len -= 64 - r;
        p += 64 - r;
        processblock(s, s->buf);
    }
    for (; len >= 64; len -= 64, p += 64) {
        processblock(s, p);
    }
    memcpy(s->buf, p, len);
}
