tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

desblapi.c (7205B)


      1 /*
      2 *  desblapi.c
      3 *
      4 *  core source file for DES-150 library
      5 *  Implement DES Modes of Operation and Triple-DES.
      6 *  Adapt DES-150 to blapi API.
      7 *
      8 * This Source Code Form is subject to the terms of the Mozilla Public
      9 * License, v. 2.0. If a copy of the MPL was not distributed with this
     10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     11 
     12 #ifdef FREEBL_NO_DEPEND
     13 #include "stubs.h"
     14 #endif
     15 
     16 #include "des.h"
     17 #include "blapii.h"
     18 #include <stddef.h>
     19 #include "secerr.h"
     20 
     21 #if defined(NSS_X86_OR_X64)
     22 /* Intel X86 CPUs do unaligned loads and stores without complaint. */
     23 #define COPY8B(to, from, ptr) \
     24    HALFPTR(to)               \
     25    [0] = HALFPTR(from)[0];   \
     26    HALFPTR(to)               \
     27    [1] = HALFPTR(from)[1];
     28 #else
     29 #define COPY8B(to, from, ptr) memcpy(to, from, 8)
     30 #endif
     31 #define COPY8BTOHALF(to, from) COPY8B(to, from, from)
     32 #define COPY8BFROMHALF(to, from) COPY8B(to, from, to)
     33 
     34 static void
     35 DES_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
     36 {
     37    while (len) {
     38        DES_Do1Block(cx->ks0, in, out);
     39        len -= 8;
     40        in += 8;
     41        out += 8;
     42    }
     43 }
     44 
     45 static void
     46 DES_EDE3_ECB(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
     47 {
     48    while (len) {
     49        DES_Do1Block(cx->ks0, in, out);
     50        len -= 8;
     51        in += 8;
     52        DES_Do1Block(cx->ks1, out, out);
     53        DES_Do1Block(cx->ks2, out, out);
     54        out += 8;
     55    }
     56 }
     57 
     58 static void NO_SANITIZE_ALIGNMENT
     59 DES_CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
     60 {
     61    const BYTE *bufend = in + len;
     62    HALF vec[2];
     63 
     64    while (in != bufend) {
     65        COPY8BTOHALF(vec, in);
     66        in += 8;
     67        vec[0] ^= cx->iv[0];
     68        vec[1] ^= cx->iv[1];
     69        DES_Do1Block(cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
     70        COPY8BFROMHALF(out, cx->iv);
     71        out += 8;
     72    }
     73 }
     74 
     75 static void NO_SANITIZE_ALIGNMENT
     76 DES_CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
     77 {
     78    const BYTE *bufend;
     79    HALF oldciphertext[2];
     80    HALF plaintext[2];
     81 
     82    for (bufend = in + len; in != bufend;) {
     83        oldciphertext[0] = cx->iv[0];
     84        oldciphertext[1] = cx->iv[1];
     85        COPY8BTOHALF(cx->iv, in);
     86        in += 8;
     87        DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
     88        plaintext[0] ^= oldciphertext[0];
     89        plaintext[1] ^= oldciphertext[1];
     90        COPY8BFROMHALF(out, plaintext);
     91        out += 8;
     92    }
     93 }
     94 
     95 static void NO_SANITIZE_ALIGNMENT
     96 DES_EDE3CBCEn(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
     97 {
     98    const BYTE *bufend = in + len;
     99    HALF vec[2];
    100 
    101    while (in != bufend) {
    102        COPY8BTOHALF(vec, in);
    103        in += 8;
    104        vec[0] ^= cx->iv[0];
    105        vec[1] ^= cx->iv[1];
    106        DES_Do1Block(cx->ks0, (BYTE *)vec, (BYTE *)cx->iv);
    107        DES_Do1Block(cx->ks1, (BYTE *)cx->iv, (BYTE *)cx->iv);
    108        DES_Do1Block(cx->ks2, (BYTE *)cx->iv, (BYTE *)cx->iv);
    109        COPY8BFROMHALF(out, cx->iv);
    110        out += 8;
    111    }
    112 }
    113 
    114 static void NO_SANITIZE_ALIGNMENT
    115 DES_EDE3CBCDe(DESContext *cx, BYTE *out, const BYTE *in, unsigned int len)
    116 {
    117    const BYTE *bufend;
    118    HALF oldciphertext[2];
    119    HALF plaintext[2];
    120 
    121    for (bufend = in + len; in != bufend;) {
    122        oldciphertext[0] = cx->iv[0];
    123        oldciphertext[1] = cx->iv[1];
    124        COPY8BTOHALF(cx->iv, in);
    125        in += 8;
    126        DES_Do1Block(cx->ks0, (BYTE *)cx->iv, (BYTE *)plaintext);
    127        DES_Do1Block(cx->ks1, (BYTE *)plaintext, (BYTE *)plaintext);
    128        DES_Do1Block(cx->ks2, (BYTE *)plaintext, (BYTE *)plaintext);
    129        plaintext[0] ^= oldciphertext[0];
    130        plaintext[1] ^= oldciphertext[1];
    131        COPY8BFROMHALF(out, plaintext);
    132        out += 8;
    133    }
    134 }
    135 
    136 DESContext *
    137 DES_AllocateContext(void)
    138 {
    139    return PORT_ZNew(DESContext);
    140 }
    141 
    142 SECStatus
    143 DES_InitContext(DESContext *cx, const unsigned char *key, unsigned int keylen,
    144                const unsigned char *iv, int mode, unsigned int encrypt,
    145                unsigned int unused)
    146 {
    147    DESDirection opposite;
    148    if (!cx) {
    149        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    150        return SECFailure;
    151    }
    152    cx->direction = encrypt ? DES_ENCRYPT : DES_DECRYPT;
    153    opposite = encrypt ? DES_DECRYPT : DES_ENCRYPT;
    154    switch (mode) {
    155        case NSS_DES: /* DES ECB */
    156            DES_MakeSchedule(cx->ks0, key, cx->direction);
    157            cx->worker = &DES_ECB;
    158            break;
    159 
    160        case NSS_DES_EDE3: /* DES EDE ECB */
    161            cx->worker = &DES_EDE3_ECB;
    162            if (encrypt) {
    163                DES_MakeSchedule(cx->ks0, key, cx->direction);
    164                DES_MakeSchedule(cx->ks1, key + 8, opposite);
    165                DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
    166            } else {
    167                DES_MakeSchedule(cx->ks2, key, cx->direction);
    168                DES_MakeSchedule(cx->ks1, key + 8, opposite);
    169                DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
    170            }
    171            break;
    172 
    173        case NSS_DES_CBC: /* DES CBC */
    174            COPY8BTOHALF(cx->iv, iv);
    175            cx->worker = encrypt ? &DES_CBCEn : &DES_CBCDe;
    176            DES_MakeSchedule(cx->ks0, key, cx->direction);
    177            break;
    178 
    179        case NSS_DES_EDE3_CBC: /* DES EDE CBC */
    180            COPY8BTOHALF(cx->iv, iv);
    181            if (encrypt) {
    182                cx->worker = &DES_EDE3CBCEn;
    183                DES_MakeSchedule(cx->ks0, key, cx->direction);
    184                DES_MakeSchedule(cx->ks1, key + 8, opposite);
    185                DES_MakeSchedule(cx->ks2, key + 16, cx->direction);
    186            } else {
    187                cx->worker = &DES_EDE3CBCDe;
    188                DES_MakeSchedule(cx->ks2, key, cx->direction);
    189                DES_MakeSchedule(cx->ks1, key + 8, opposite);
    190                DES_MakeSchedule(cx->ks0, key + 16, cx->direction);
    191            }
    192            break;
    193 
    194        default:
    195            PORT_SetError(SEC_ERROR_INVALID_ARGS);
    196            return SECFailure;
    197    }
    198    return SECSuccess;
    199 }
    200 
    201 DESContext *
    202 DES_CreateContext(const BYTE *key, const BYTE *iv, int mode, PRBool encrypt)
    203 {
    204    DESContext *cx = PORT_ZNew(DESContext);
    205    SECStatus rv = DES_InitContext(cx, key, 0, iv, mode, encrypt, 0);
    206 
    207    if (rv != SECSuccess) {
    208        PORT_ZFree(cx, sizeof *cx);
    209        cx = NULL;
    210    }
    211    return cx;
    212 }
    213 
    214 void
    215 DES_DestroyContext(DESContext *cx, PRBool freeit)
    216 {
    217    if (cx) {
    218        memset(cx, 0, sizeof *cx);
    219        if (freeit)
    220            PORT_Free(cx);
    221    }
    222 }
    223 
    224 SECStatus
    225 DES_Encrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
    226            unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
    227 {
    228 
    229    if ((inLen % 8) != 0 || maxOutLen < inLen || !cx ||
    230        cx->direction != DES_ENCRYPT) {
    231        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    232        return SECFailure;
    233    }
    234 
    235    cx->worker(cx, out, in, inLen);
    236    if (outLen)
    237        *outLen = inLen;
    238    return SECSuccess;
    239 }
    240 
    241 SECStatus
    242 DES_Decrypt(DESContext *cx, BYTE *out, unsigned int *outLen,
    243            unsigned int maxOutLen, const BYTE *in, unsigned int inLen)
    244 {
    245 
    246    if ((inLen % 8) != 0 || maxOutLen < inLen || !cx ||
    247        cx->direction != DES_DECRYPT) {
    248        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    249        return SECFailure;
    250    }
    251 
    252    cx->worker(cx, out, in, inLen);
    253    if (outLen)
    254        *outLen = inLen;
    255    return SECSuccess;
    256 }