/*
 *  desblapi.c
 *
 *  core source file for DES-150 library
 *  Implement DES Modes of Operation and Triple-DES.
 *  Adapt DES-150 to blapi API.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#endif

#include "des.h"
#include "blapii.h"
#include <stddef.h>
#include "secerr.h"

#if defined(NSS_X86_OR_X64)
/* Intel X86 CPUs do unaligned loads and stores without complaint. */
#define COPY8B(to, from, ptr) \
    HALFPTR(to)               \
    [0] = HALFPTR(from)[0];   \
    HALFPTR(to)               \
    [1] = HALFPTR(from)[1];
#else
#define COPY8B(to, from, ptr) memcpy(to, from, 8)
#endif
#define COPY8BTOHALF(to, from) COPY8B(to, from, from)
#define COPY8BFROMHALF(to, from) COPY8B(to, from, to)

static void
DES_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
{
    while (len) {
        DES_Do1Block(cx->ks0, in, out);
        len -= 8;
        in += 8;
        out += 8;
    }
}

static void
DES_EDE3_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
{
    while (len) {
        DES_Do1Block(cx->ks0, in, out);
        len -= 8;
        in += 8;
        DES_Do1Block(cx->ks1, out, out);
        DES_Do1Block(cx->ks2, out, out);
        out += 8;
    }
}

static void NO_SANITIZE_ALIGNMENT
DES_CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
{
    const BYTE *bufend = in + len;
    HALF vec[2];

    while (in != bufend) {
        COPY8BTOHALF(vec, in);
        in += 8;
        vec[0] ^= cx->iv[0];
        vec[1] ^= cx->iv[1];
        DES_Do1Block(cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
        COPY8BFROMHALF(out, cx->iv);
        out += 8;
    }
}

static void NO_SANITIZE_ALIGNMENT
DES_CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
{
    const BYTE *bufend;
    HALF oldciphertext[2];
    HALF plaintext[2];

    for (bufend = in + len; in != bufend;) {
        oldciphertext[0] = cx->iv[0];
        oldciphertext[1] = cx->iv[1];
        COPY8BTOHALF(cx->iv, in);
        in += 8;
        DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
        plaintext[0] ^= oldciphertext[0];
        plaintext[1] ^= oldciphertext[1];
        COPY8BFROMHALF(out, plaintext);
        out += 8;
    }
}

static void NO_SANITIZE_ALIGNMENT
DES_EDE3CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
{
    const BYTE *bufend = in + len;
    HALF vec[2];

    while (in != bufend) {
        COPY8BTOHALF(vec, in);
        in += 8;
        vec[0] ^= cx->iv[0];
        vec[1] ^= cx->iv[1];
        DES_Do1Block(cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
        DES_Do1Block(cx->ks1, (BYTE *)cx->iv, (BYTE *)cx->iv);
        DES_Do1Block(cx->ks2, (BYTE *)cx->iv, (BYTE *)cx->iv);
        COPY8BFROMHALF(out, cx->iv);
        out += 8;
    }
}

static void NO_SANITIZE_ALIGNMENT
DES_EDE3CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
{
    const BYTE *bufend;
    HALF oldciphertext[2];
    HALF plaintext[2];

    for (bufend = in + len; in != bufend;) {
        oldciphertext[0] = cx->iv[0];
        oldciphertext[1] = cx->iv[1];
        COPY8BTOHALF(cx->iv, in);
        in += 8;
        DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
        DES_Do1Block(cx->ks1, (BYTE *)plaintext, (BYTE *)plaintext);
        DES_Do1Block(cx->ks2, (BYTE *)plaintext, (BYTE *)plaintext);
        plaintext[0] ^= oldciphertext[0];
        plaintext[1] ^= oldciphertext[1];
        COPY8BFROMHALF(out, plaintext);
        out += 8;
    }
}

DESContext *
DES_AllocateContext(void)
{
    return PORT_ZNew(DESContext);
}

SECStatus
DES_InitContext(DESContext *cx, const unsigned char *key, unsigned int keylen,
                const unsigned char *iv, int mode, unsigned int encrypt,
                unsigned int unused)
{
    DESDirection opposite;
    if (!cx) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    cx->direction = encrypt ? DES_ENCRYPT : DES_DECRYPT;
    opposite = encrypt ? DES_DECRYPT : DES_ENCRYPT;
    switch (mode) {
        case NSS_DES: /* DES ECB */
            DES_MakeSchedule(cx->ks0, key, cx->direction);
            cx->worker = &DES_ECB;
            break;

        case NSS_DES_EDE3: /* DES EDE ECB */
            cx->worker = &DES_EDE3_ECB;
            if (encrypt) {
                DES_MakeSchedule(cx->ks0, key, cx->direction);
                DES_MakeSchedule(cx->ks1, key + 8, opposite);
                DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
            } else {
                DES_MakeSchedule(cx->ks2, key, cx->direction);
                DES_MakeSchedule(cx->ks1, key + 8, opposite);
                DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
            }
            break;

        case NSS_DES_CBC: /* DES CBC */
            COPY8BTOHALF(cx->iv, iv);
            cx->worker = encrypt ? &DES_CBCEn : &DES_CBCDe;
            DES_MakeSchedule(cx->ks0, key, cx->direction);
            break;

        case NSS_DES_EDE3_CBC: /* DES EDE CBC */
            COPY8BTOHALF(cx->iv, iv);
            if (encrypt) {
                cx->worker = &DES_EDE3CBCEn;
                DES_MakeSchedule(cx->ks0, key, cx->direction);
                DES_MakeSchedule(cx->ks1, key + 8, opposite);
                DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
            } else {
                cx->worker = &DES_EDE3CBCDe;
                DES_MakeSchedule(cx->ks2, key, cx->direction);
                DES_MakeSchedule(cx->ks1, key + 8, opposite);
                DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
            }
            break;

        default:
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
            return SECFailure;
    }
    return SECSuccess;
}

DESContext *
DES_CreateContext(const BYTE *key, const BYTE *iv, int mode, PRBool encrypt)
{
    DESContext *cx = PORT_ZNew(DESContext);
    SECStatus rv = DES_InitContext(cx, key, 0, iv, mode, encrypt, 0);

    if (rv != SECSuccess) {
        PORT_ZFree(cx, sizeof *cx);
        cx = NULL;
    }
    return cx;
}

void
DES_DestroyContext(DESContext *cx, PRBool freeit)
{
    if (cx) {
        memset(cx, 0, sizeof *cx);
        if (freeit)
            PORT_Free(cx);
    }
}

SECStatus
DES_Encrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
            unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
{

    if ((inLen % 8) != 0 || maxOutLen < inLen || !cx ||
        cx->direction != DES_ENCRYPT) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    cx->worker(cx, out, in, inLen);
    if (outLen)
        *outLen = inLen;
    return SECSuccess;
}

SECStatus
DES_Decrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
            unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
{

    if ((inLen % 8) != 0 || maxOutLen < inLen || !cx ||
        cx->direction != DES_DECRYPT) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    cx->worker(cx, out, in, inLen);
    if (outLen)
        *outLen = inLen;
    return SECSuccess;
}
