"Fossies" - the Fresh Open Source Software Archive

Member "nss-3.35/nss/lib/freebl/alg2268.c" (18 Jan 2018, 14618 Bytes) of package /linux/misc/nss-3.35.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "alg2268.c" see the Fossies "Dox" file reference documentation.

    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 }