tor-browser

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

alg2268.c (14627B)


      1 /*
      2 * alg2268.c - implementation of the algorithm in RFC 2268
      3 *
      4 * This Source Code Form is subject to the terms of the Mozilla Public
      5 * License, v. 2.0. If a copy of the MPL was not distributed with this
      6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      7 
      8 #ifdef FREEBL_NO_DEPEND
      9 #include "../stubs.h"
     10 #endif
     11 
     12 #include "../blapi.h"
     13 #include "../blapii.h"
     14 #include "secerr.h"
     15 #ifdef XP_UNIX_XXX
     16 #include <stddef.h> /* for ptrdiff_t */
     17 #endif
     18 
     19 /*
     20 ** RC2 symmetric block cypher
     21 */
     22 
     23 typedef SECStatus(rc2Func)(RC2Context *cx, unsigned char *output,
     24                           const unsigned char *input, unsigned int inputLen);
     25 
     26 /* forward declarations */
     27 static rc2Func rc2_EncryptECB;
     28 static rc2Func rc2_DecryptECB;
     29 static rc2Func rc2_EncryptCBC;
     30 static rc2Func rc2_DecryptCBC;
     31 
     32 typedef union {
     33    PRUint32 l[2];
     34    PRUint16 s[4];
     35    PRUint8 b[8];
     36 } RC2Block;
     37 
     38 struct RC2ContextStr {
     39    union {
     40        PRUint8 Kb[128];
     41        PRUint16 Kw[64];
     42    } u;
     43    RC2Block iv;
     44    rc2Func *enc;
     45    rc2Func *dec;
     46 };
     47 
     48 #define B u.Kb
     49 #define K u.Kw
     50 #define BYTESWAP(x) ((x) << 8 | (x) >> 8)
     51 #define SWAPK(i) cx->K[i] = (tmpS = cx->K[i], BYTESWAP(tmpS))
     52 #define RC2_BLOCK_SIZE 8
     53 
     54 #define LOAD_HARD(R)                           \
     55    R[0] = (PRUint16)input[1] << 8 | input[0]; \
     56    R[1] = (PRUint16)input[3] << 8 | input[2]; \
     57    R[2] = (PRUint16)input[5] << 8 | input[4]; \
     58    R[3] = (PRUint16)input[7] << 8 | input[6];
     59 #define LOAD_EASY(R)               \
     60    R[0] = ((PRUint16 *)input)[0]; \
     61    R[1] = ((PRUint16 *)input)[1]; \
     62    R[2] = ((PRUint16 *)input)[2]; \
     63    R[3] = ((PRUint16 *)input)[3];
     64 #define STORE_HARD(R)                 \
     65    output[0] = (PRUint8)(R[0]);      \
     66    output[1] = (PRUint8)(R[0] >> 8); \
     67    output[2] = (PRUint8)(R[1]);      \
     68    output[3] = (PRUint8)(R[1] >> 8); \
     69    output[4] = (PRUint8)(R[2]);      \
     70    output[5] = (PRUint8)(R[2] >> 8); \
     71    output[6] = (PRUint8)(R[3]);      \
     72    output[7] = (PRUint8)(R[3] >> 8);
     73 #define STORE_EASY(R)               \
     74    ((PRUint16 *)output)[0] = R[0]; \
     75    ((PRUint16 *)output)[1] = R[1]; \
     76    ((PRUint16 *)output)[2] = R[2]; \
     77    ((PRUint16 *)output)[3] = R[3];
     78 
     79 #if defined(NSS_X86_OR_X64)
     80 #define LOAD(R) LOAD_EASY(R)
     81 #define STORE(R) STORE_EASY(R)
     82 #elif !defined(IS_LITTLE_ENDIAN)
     83 #define LOAD(R) LOAD_HARD(R)
     84 #define STORE(R) STORE_HARD(R)
     85 #else
     86 #define LOAD(R)                 \
     87    if ((ptrdiff_t)input & 1) { \
     88        LOAD_HARD(R)            \
     89    } else {                    \
     90        LOAD_EASY(R)            \
     91    }
     92 #define STORE(R)                \
     93    if ((ptrdiff_t)input & 1) { \
     94        STORE_HARD(R)           \
     95    } else {                    \
     96        STORE_EASY(R)           \
     97    }
     98 #endif
     99 
    100 static const PRUint8 S[256] = {
    101    0331, 0170, 0371, 0304, 0031, 0335, 0265, 0355, 0050, 0351, 0375, 0171, 0112, 0240, 0330, 0235,
    102    0306, 0176, 0067, 0203, 0053, 0166, 0123, 0216, 0142, 0114, 0144, 0210, 0104, 0213, 0373, 0242,
    103    0027, 0232, 0131, 0365, 0207, 0263, 0117, 0023, 0141, 0105, 0155, 0215, 0011, 0201, 0175, 0062,
    104    0275, 0217, 0100, 0353, 0206, 0267, 0173, 0013, 0360, 0225, 0041, 0042, 0134, 0153, 0116, 0202,
    105    0124, 0326, 0145, 0223, 0316, 0140, 0262, 0034, 0163, 0126, 0300, 0024, 0247, 0214, 0361, 0334,
    106    0022, 0165, 0312, 0037, 0073, 0276, 0344, 0321, 0102, 0075, 0324, 0060, 0243, 0074, 0266, 0046,
    107    0157, 0277, 0016, 0332, 0106, 0151, 0007, 0127, 0047, 0362, 0035, 0233, 0274, 0224, 0103, 0003,
    108    0370, 0021, 0307, 0366, 0220, 0357, 0076, 0347, 0006, 0303, 0325, 0057, 0310, 0146, 0036, 0327,
    109    0010, 0350, 0352, 0336, 0200, 0122, 0356, 0367, 0204, 0252, 0162, 0254, 0065, 0115, 0152, 0052,
    110    0226, 0032, 0322, 0161, 0132, 0025, 0111, 0164, 0113, 0237, 0320, 0136, 0004, 0030, 0244, 0354,
    111    0302, 0340, 0101, 0156, 0017, 0121, 0313, 0314, 0044, 0221, 0257, 0120, 0241, 0364, 0160, 0071,
    112    0231, 0174, 0072, 0205, 0043, 0270, 0264, 0172, 0374, 0002, 0066, 0133, 0045, 0125, 0227, 0061,
    113    0055, 0135, 0372, 0230, 0343, 0212, 0222, 0256, 0005, 0337, 0051, 0020, 0147, 0154, 0272, 0311,
    114    0323, 0000, 0346, 0317, 0341, 0236, 0250, 0054, 0143, 0026, 0001, 0077, 0130, 0342, 0211, 0251,
    115    0015, 0070, 0064, 0033, 0253, 0063, 0377, 0260, 0273, 0110, 0014, 0137, 0271, 0261, 0315, 0056,
    116    0305, 0363, 0333, 0107, 0345, 0245, 0234, 0167, 0012, 0246, 0040, 0150, 0376, 0177, 0301, 0255
    117 };
    118 
    119 RC2Context *
    120 RC2_AllocateContext(void)
    121 {
    122    return PORT_ZNew(RC2Context);
    123 }
    124 SECStatus
    125 RC2_InitContext(RC2Context *cx, const unsigned char *key, unsigned int len,
    126                const unsigned char *input, int mode, unsigned int efLen8,
    127                unsigned int unused)
    128 {
    129    PRUint8 *L, *L2;
    130    int i;
    131 #if !defined(IS_LITTLE_ENDIAN)
    132    PRUint16 tmpS;
    133 #endif
    134    PRUint8 tmpB;
    135 
    136    if (!key || !cx || !len || len > (sizeof cx->B) ||
    137        efLen8 > (sizeof cx->B)) {
    138        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    139        return SECFailure;
    140    }
    141    if (mode == NSS_RC2) {
    142        /* groovy */
    143    } else if (mode == NSS_RC2_CBC) {
    144        if (!input) {
    145            PORT_SetError(SEC_ERROR_INVALID_ARGS);
    146            return SECFailure;
    147        }
    148    } else {
    149        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    150        return SECFailure;
    151    }
    152 
    153    if (mode == NSS_RC2_CBC) {
    154        cx->enc = &rc2_EncryptCBC;
    155        cx->dec = &rc2_DecryptCBC;
    156        LOAD(cx->iv.s);
    157    } else {
    158        cx->enc = &rc2_EncryptECB;
    159        cx->dec = &rc2_DecryptECB;
    160    }
    161 
    162    /* Step 0. Copy key into table. */
    163    memcpy(cx->B, key, len);
    164 
    165    /* Step 1. Compute all values to the right of the key. */
    166    L2 = cx->B;
    167    L = L2 + len;
    168    tmpB = L[-1];
    169    for (i = (sizeof cx->B) - len; i > 0; --i) {
    170        *L++ = tmpB = S[(PRUint8)(tmpB + *L2++)];
    171    }
    172 
    173    /* step 2. Adjust left most byte of effective key. */
    174    i = (sizeof cx->B) - efLen8;
    175    L = cx->B + i;
    176    *L = tmpB = S[*L]; /* mask is always 0xff */
    177 
    178    /* step 3. Recompute all values to the left of effective key. */
    179    L2 = --L + efLen8;
    180    while (L >= cx->B) {
    181        *L-- = tmpB = S[tmpB ^ *L2--];
    182    }
    183 
    184 #if !defined(IS_LITTLE_ENDIAN)
    185    for (i = 63; i >= 0; --i) {
    186        SWAPK(i); /* candidate for unrolling */
    187    }
    188 #endif
    189    return SECSuccess;
    190 }
    191 
    192 /*
    193 ** Create a new RC2 context suitable for RC2 encryption/decryption.
    194 **  "key" raw key data
    195 **  "len" the number of bytes of key data
    196 **  "iv" is the CBC initialization vector (if mode is NSS_RC2_CBC)
    197 **  "mode" one of NSS_RC2 or NSS_RC2_CBC
    198 **  "effectiveKeyLen" in bytes, not bits.
    199 **
    200 ** When mode is set to NSS_RC2_CBC the RC2 cipher is run in "cipher block
    201 ** chaining" mode.
    202 */
    203 RC2Context *
    204 RC2_CreateContext(const unsigned char *key, unsigned int len,
    205                  const unsigned char *iv, int mode, unsigned efLen8)
    206 {
    207    RC2Context *cx = PORT_ZNew(RC2Context);
    208    if (cx) {
    209        SECStatus rv = RC2_InitContext(cx, key, len, iv, mode, efLen8, 0);
    210        if (rv != SECSuccess) {
    211            RC2_DestroyContext(cx, PR_TRUE);
    212            cx = NULL;
    213        }
    214    }
    215    return cx;
    216 }
    217 
    218 /*
    219 ** Destroy an RC2 encryption/decryption context.
    220 **  "cx" the context
    221 **  "freeit" if PR_TRUE then free the object as well as its sub-objects
    222 */
    223 void
    224 RC2_DestroyContext(RC2Context *cx, PRBool freeit)
    225 {
    226    if (cx) {
    227        memset(cx, 0, sizeof *cx);
    228        if (freeit) {
    229            PORT_Free(cx);
    230        }
    231    }
    232 }
    233 
    234 #define ROL(x, k) (x << k | x >> (16 - k))
    235 #define MIX(j)                                           \
    236    R0 = R0 + cx->K[4 * j + 0] + (R3 & R2) + (~R3 & R1); \
    237    R0 = ROL(R0, 1);                                     \
    238    R1 = R1 + cx->K[4 * j + 1] + (R0 & R3) + (~R0 & R2); \
    239    R1 = ROL(R1, 2);                                     \
    240    R2 = R2 + cx->K[4 * j + 2] + (R1 & R0) + (~R1 & R3); \
    241    R2 = ROL(R2, 3);                                     \
    242    R3 = R3 + cx->K[4 * j + 3] + (R2 & R1) + (~R2 & R0); \
    243    R3 = ROL(R3, 5)
    244 #define MASH                  \
    245    R0 = R0 + cx->K[R3 & 63]; \
    246    R1 = R1 + cx->K[R0 & 63]; \
    247    R2 = R2 + cx->K[R1 & 63]; \
    248    R3 = R3 + cx->K[R2 & 63]
    249 
    250 /* Encrypt one block */
    251 static void
    252 rc2_Encrypt1Block(RC2Context *cx, RC2Block *output, RC2Block *input)
    253 {
    254    register PRUint16 R0, R1, R2, R3;
    255 
    256    /* step 1. Initialize input. */
    257    R0 = input->s[0];
    258    R1 = input->s[1];
    259    R2 = input->s[2];
    260    R3 = input->s[3];
    261 
    262    /* step 2.  Expand Key (already done, in context) */
    263    /* step 3.  j = 0 */
    264    /* step 4.  Perform 5 mixing rounds. */
    265 
    266    MIX(0);
    267    MIX(1);
    268    MIX(2);
    269    MIX(3);
    270    MIX(4);
    271 
    272    /* step 5. Perform 1 mashing round. */
    273    MASH;
    274 
    275    /* step 6. Perform 6 mixing rounds. */
    276 
    277    MIX(5);
    278    MIX(6);
    279    MIX(7);
    280    MIX(8);
    281    MIX(9);
    282    MIX(10);
    283 
    284    /* step 7. Perform 1 mashing round. */
    285    MASH;
    286 
    287    /* step 8. Perform 5 mixing rounds. */
    288 
    289    MIX(11);
    290    MIX(12);
    291    MIX(13);
    292    MIX(14);
    293    MIX(15);
    294 
    295    /* output results */
    296    output->s[0] = R0;
    297    output->s[1] = R1;
    298    output->s[2] = R2;
    299    output->s[3] = R3;
    300 }
    301 
    302 #define ROR(x, k) (x >> k | x << (16 - k))
    303 #define R_MIX(j)                                         \
    304    R3 = ROR(R3, 5);                                     \
    305    R3 = R3 - cx->K[4 * j + 3] - (R2 & R1) - (~R2 & R0); \
    306    R2 = ROR(R2, 3);                                     \
    307    R2 = R2 - cx->K[4 * j + 2] - (R1 & R0) - (~R1 & R3); \
    308    R1 = ROR(R1, 2);                                     \
    309    R1 = R1 - cx->K[4 * j + 1] - (R0 & R3) - (~R0 & R2); \
    310    R0 = ROR(R0, 1);                                     \
    311    R0 = R0 - cx->K[4 * j + 0] - (R3 & R2) - (~R3 & R1)
    312 #define R_MASH                \
    313    R3 = R3 - cx->K[R2 & 63]; \
    314    R2 = R2 - cx->K[R1 & 63]; \
    315    R1 = R1 - cx->K[R0 & 63]; \
    316    R0 = R0 - cx->K[R3 & 63]
    317 
    318 /* Encrypt one block */
    319 static void
    320 rc2_Decrypt1Block(RC2Context *cx, RC2Block *output, RC2Block *input)
    321 {
    322    register PRUint16 R0, R1, R2, R3;
    323 
    324    /* step 1. Initialize input. */
    325    R0 = input->s[0];
    326    R1 = input->s[1];
    327    R2 = input->s[2];
    328    R3 = input->s[3];
    329 
    330    /* step 2.  Expand Key (already done, in context) */
    331    /* step 3.  j = 63 */
    332    /* step 4.  Perform 5 r_mixing rounds. */
    333    R_MIX(15);
    334    R_MIX(14);
    335    R_MIX(13);
    336    R_MIX(12);
    337    R_MIX(11);
    338 
    339    /* step 5.  Perform 1 r_mashing round. */
    340    R_MASH;
    341 
    342    /* step 6.  Perform 6 r_mixing rounds. */
    343    R_MIX(10);
    344    R_MIX(9);
    345    R_MIX(8);
    346    R_MIX(7);
    347    R_MIX(6);
    348    R_MIX(5);
    349 
    350    /* step 7.  Perform 1 r_mashing round. */
    351    R_MASH;
    352 
    353    /* step 8.  Perform 5 r_mixing rounds. */
    354    R_MIX(4);
    355    R_MIX(3);
    356    R_MIX(2);
    357    R_MIX(1);
    358    R_MIX(0);
    359 
    360    /* output results */
    361    output->s[0] = R0;
    362    output->s[1] = R1;
    363    output->s[2] = R2;
    364    output->s[3] = R3;
    365 }
    366 
    367 static SECStatus NO_SANITIZE_ALIGNMENT
    368 rc2_EncryptECB(RC2Context *cx, unsigned char *output,
    369               const unsigned char *input, unsigned int inputLen)
    370 {
    371    RC2Block iBlock;
    372 
    373    while (inputLen > 0) {
    374        LOAD(iBlock.s)
    375        rc2_Encrypt1Block(cx, &iBlock, &iBlock);
    376        STORE(iBlock.s)
    377        output += RC2_BLOCK_SIZE;
    378        input += RC2_BLOCK_SIZE;
    379        inputLen -= RC2_BLOCK_SIZE;
    380    }
    381    return SECSuccess;
    382 }
    383 
    384 static SECStatus NO_SANITIZE_ALIGNMENT
    385 rc2_DecryptECB(RC2Context *cx, unsigned char *output,
    386               const unsigned char *input, unsigned int inputLen)
    387 {
    388    RC2Block iBlock;
    389 
    390    while (inputLen > 0) {
    391        LOAD(iBlock.s)
    392        rc2_Decrypt1Block(cx, &iBlock, &iBlock);
    393        STORE(iBlock.s)
    394        output += RC2_BLOCK_SIZE;
    395        input += RC2_BLOCK_SIZE;
    396        inputLen -= RC2_BLOCK_SIZE;
    397    }
    398    return SECSuccess;
    399 }
    400 
    401 static SECStatus NO_SANITIZE_ALIGNMENT
    402 rc2_EncryptCBC(RC2Context *cx, unsigned char *output,
    403               const unsigned char *input, unsigned int inputLen)
    404 {
    405    RC2Block iBlock;
    406 
    407    while (inputLen > 0) {
    408 
    409        LOAD(iBlock.s)
    410        iBlock.l[0] ^= cx->iv.l[0];
    411        iBlock.l[1] ^= cx->iv.l[1];
    412        rc2_Encrypt1Block(cx, &iBlock, &iBlock);
    413        cx->iv = iBlock;
    414        STORE(iBlock.s)
    415        output += RC2_BLOCK_SIZE;
    416        input += RC2_BLOCK_SIZE;
    417        inputLen -= RC2_BLOCK_SIZE;
    418    }
    419    return SECSuccess;
    420 }
    421 
    422 static SECStatus NO_SANITIZE_ALIGNMENT
    423 rc2_DecryptCBC(RC2Context *cx, unsigned char *output,
    424               const unsigned char *input, unsigned int inputLen)
    425 {
    426    RC2Block iBlock;
    427    RC2Block oBlock;
    428 
    429    while (inputLen > 0) {
    430        LOAD(iBlock.s)
    431        rc2_Decrypt1Block(cx, &oBlock, &iBlock);
    432        oBlock.l[0] ^= cx->iv.l[0];
    433        oBlock.l[1] ^= cx->iv.l[1];
    434        cx->iv = iBlock;
    435        STORE(oBlock.s)
    436        output += RC2_BLOCK_SIZE;
    437        input += RC2_BLOCK_SIZE;
    438        inputLen -= RC2_BLOCK_SIZE;
    439    }
    440    return SECSuccess;
    441 }
    442 
    443 /*
    444 ** Perform RC2 encryption.
    445 **  "cx" the context
    446 **  "output" the output buffer to store the encrypted data.
    447 **  "outputLen" how much data is stored in "output". Set by the routine
    448 **     after some data is stored in output.
    449 **  "maxOutputLen" the maximum amount of data that can ever be
    450 **     stored in "output"
    451 **  "input" the input data
    452 **  "inputLen" the amount of input data
    453 */
    454 SECStatus
    455 RC2_Encrypt(RC2Context *cx, unsigned char *output,
    456            unsigned int *outputLen, unsigned int maxOutputLen,
    457            const unsigned char *input, unsigned int inputLen)
    458 {
    459    SECStatus rv = SECSuccess;
    460    if (inputLen) {
    461        if (inputLen % RC2_BLOCK_SIZE) {
    462            PORT_SetError(SEC_ERROR_INPUT_LEN);
    463            return SECFailure;
    464        }
    465        if (maxOutputLen < inputLen) {
    466            PORT_SetError(SEC_ERROR_OUTPUT_LEN);
    467            return SECFailure;
    468        }
    469        rv = (*cx->enc)(cx, output, input, inputLen);
    470    }
    471    if (rv == SECSuccess) {
    472        *outputLen = inputLen;
    473    }
    474    return rv;
    475 }
    476 
    477 /*
    478 ** Perform RC2 decryption.
    479 **  "cx" the context
    480 **  "output" the output buffer to store the decrypted data.
    481 **  "outputLen" how much data is stored in "output". Set by the routine
    482 **     after some data is stored in output.
    483 **  "maxOutputLen" the maximum amount of data that can ever be
    484 **     stored in "output"
    485 **  "input" the input data
    486 **  "inputLen" the amount of input data
    487 */
    488 SECStatus
    489 RC2_Decrypt(RC2Context *cx, unsigned char *output,
    490            unsigned int *outputLen, unsigned int maxOutputLen,
    491            const unsigned char *input, unsigned int inputLen)
    492 {
    493    SECStatus rv = SECSuccess;
    494    if (inputLen) {
    495        if (inputLen % RC2_BLOCK_SIZE) {
    496            PORT_SetError(SEC_ERROR_INPUT_LEN);
    497            return SECFailure;
    498        }
    499        if (maxOutputLen < inputLen) {
    500            PORT_SetError(SEC_ERROR_OUTPUT_LEN);
    501            return SECFailure;
    502        }
    503        rv = (*cx->dec)(cx, output, input, inputLen);
    504    }
    505    if (rv == SECSuccess) {
    506        *outputLen = inputLen;
    507    }
    508    return rv;
    509 }