1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/freebl/alg2268.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,485 @@ 1.4 +/* 1.5 + * alg2268.c - implementation of the algorithm in RFC 2268 1.6 + * 1.7 + * This Source Code Form is subject to the terms of the Mozilla Public 1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.10 + 1.11 +#ifdef FREEBL_NO_DEPEND 1.12 +#include "stubs.h" 1.13 +#endif 1.14 + 1.15 +#include "blapi.h" 1.16 +#include "secerr.h" 1.17 +#ifdef XP_UNIX_XXX 1.18 +#include <stddef.h> /* for ptrdiff_t */ 1.19 +#endif 1.20 + 1.21 +/* 1.22 +** RC2 symmetric block cypher 1.23 +*/ 1.24 + 1.25 +typedef SECStatus (rc2Func)(RC2Context *cx, unsigned char *output, 1.26 + const unsigned char *input, unsigned int inputLen); 1.27 + 1.28 +/* forward declarations */ 1.29 +static rc2Func rc2_EncryptECB; 1.30 +static rc2Func rc2_DecryptECB; 1.31 +static rc2Func rc2_EncryptCBC; 1.32 +static rc2Func rc2_DecryptCBC; 1.33 + 1.34 +typedef union { 1.35 + PRUint32 l[2]; 1.36 + PRUint16 s[4]; 1.37 + PRUint8 b[8]; 1.38 +} RC2Block; 1.39 + 1.40 +struct RC2ContextStr { 1.41 + union { 1.42 + PRUint8 Kb[128]; 1.43 + PRUint16 Kw[64]; 1.44 + } u; 1.45 + RC2Block iv; 1.46 + rc2Func *enc; 1.47 + rc2Func *dec; 1.48 +}; 1.49 + 1.50 +#define B u.Kb 1.51 +#define K u.Kw 1.52 +#define BYTESWAP(x) ((x) << 8 | (x) >> 8) 1.53 +#define SWAPK(i) cx->K[i] = (tmpS = cx->K[i], BYTESWAP(tmpS)) 1.54 +#define RC2_BLOCK_SIZE 8 1.55 + 1.56 +#define LOAD_HARD(R) \ 1.57 + R[0] = (PRUint16)input[1] << 8 | input[0]; \ 1.58 + R[1] = (PRUint16)input[3] << 8 | input[2]; \ 1.59 + R[2] = (PRUint16)input[5] << 8 | input[4]; \ 1.60 + R[3] = (PRUint16)input[7] << 8 | input[6]; 1.61 +#define LOAD_EASY(R) \ 1.62 + R[0] = ((PRUint16 *)input)[0]; \ 1.63 + R[1] = ((PRUint16 *)input)[1]; \ 1.64 + R[2] = ((PRUint16 *)input)[2]; \ 1.65 + R[3] = ((PRUint16 *)input)[3]; 1.66 +#define STORE_HARD(R) \ 1.67 + output[0] = (PRUint8)(R[0]); output[1] = (PRUint8)(R[0] >> 8); \ 1.68 + output[2] = (PRUint8)(R[1]); output[3] = (PRUint8)(R[1] >> 8); \ 1.69 + output[4] = (PRUint8)(R[2]); output[5] = (PRUint8)(R[2] >> 8); \ 1.70 + output[6] = (PRUint8)(R[3]); output[7] = (PRUint8)(R[3] >> 8); 1.71 +#define STORE_EASY(R) \ 1.72 + ((PRUint16 *)output)[0] = R[0]; \ 1.73 + ((PRUint16 *)output)[1] = R[1]; \ 1.74 + ((PRUint16 *)output)[2] = R[2]; \ 1.75 + ((PRUint16 *)output)[3] = R[3]; 1.76 + 1.77 +#if defined (NSS_X86_OR_X64) 1.78 +#define LOAD(R) LOAD_EASY(R) 1.79 +#define STORE(R) STORE_EASY(R) 1.80 +#elif !defined(IS_LITTLE_ENDIAN) 1.81 +#define LOAD(R) LOAD_HARD(R) 1.82 +#define STORE(R) STORE_HARD(R) 1.83 +#else 1.84 +#define LOAD(R) if ((ptrdiff_t)input & 1) { LOAD_HARD(R) } else { LOAD_EASY(R) } 1.85 +#define STORE(R) if ((ptrdiff_t)input & 1) { STORE_HARD(R) } else { STORE_EASY(R) } 1.86 +#endif 1.87 + 1.88 +static const PRUint8 S[256] = { 1.89 +0331,0170,0371,0304,0031,0335,0265,0355,0050,0351,0375,0171,0112,0240,0330,0235, 1.90 +0306,0176,0067,0203,0053,0166,0123,0216,0142,0114,0144,0210,0104,0213,0373,0242, 1.91 +0027,0232,0131,0365,0207,0263,0117,0023,0141,0105,0155,0215,0011,0201,0175,0062, 1.92 +0275,0217,0100,0353,0206,0267,0173,0013,0360,0225,0041,0042,0134,0153,0116,0202, 1.93 +0124,0326,0145,0223,0316,0140,0262,0034,0163,0126,0300,0024,0247,0214,0361,0334, 1.94 +0022,0165,0312,0037,0073,0276,0344,0321,0102,0075,0324,0060,0243,0074,0266,0046, 1.95 +0157,0277,0016,0332,0106,0151,0007,0127,0047,0362,0035,0233,0274,0224,0103,0003, 1.96 +0370,0021,0307,0366,0220,0357,0076,0347,0006,0303,0325,0057,0310,0146,0036,0327, 1.97 +0010,0350,0352,0336,0200,0122,0356,0367,0204,0252,0162,0254,0065,0115,0152,0052, 1.98 +0226,0032,0322,0161,0132,0025,0111,0164,0113,0237,0320,0136,0004,0030,0244,0354, 1.99 +0302,0340,0101,0156,0017,0121,0313,0314,0044,0221,0257,0120,0241,0364,0160,0071, 1.100 +0231,0174,0072,0205,0043,0270,0264,0172,0374,0002,0066,0133,0045,0125,0227,0061, 1.101 +0055,0135,0372,0230,0343,0212,0222,0256,0005,0337,0051,0020,0147,0154,0272,0311, 1.102 +0323,0000,0346,0317,0341,0236,0250,0054,0143,0026,0001,0077,0130,0342,0211,0251, 1.103 +0015,0070,0064,0033,0253,0063,0377,0260,0273,0110,0014,0137,0271,0261,0315,0056, 1.104 +0305,0363,0333,0107,0345,0245,0234,0167,0012,0246,0040,0150,0376,0177,0301,0255 1.105 +}; 1.106 + 1.107 +RC2Context * RC2_AllocateContext(void) 1.108 +{ 1.109 + return PORT_ZNew(RC2Context); 1.110 +} 1.111 +SECStatus 1.112 +RC2_InitContext(RC2Context *cx, const unsigned char *key, unsigned int len, 1.113 + const unsigned char *input, int mode, unsigned int efLen8, 1.114 + unsigned int unused) 1.115 +{ 1.116 + PRUint8 *L,*L2; 1.117 + int i; 1.118 +#if !defined(IS_LITTLE_ENDIAN) 1.119 + PRUint16 tmpS; 1.120 +#endif 1.121 + PRUint8 tmpB; 1.122 + 1.123 + if (!key || !cx || !len || len > (sizeof cx->B) || 1.124 + efLen8 > (sizeof cx->B)) { 1.125 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.126 + return SECFailure; 1.127 + } 1.128 + if (mode == NSS_RC2) { 1.129 + /* groovy */ 1.130 + } else if (mode == NSS_RC2_CBC) { 1.131 + if (!input) { 1.132 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.133 + return SECFailure; 1.134 + } 1.135 + } else { 1.136 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.137 + return SECFailure; 1.138 + } 1.139 + 1.140 + if (mode == NSS_RC2_CBC) { 1.141 + cx->enc = & rc2_EncryptCBC; 1.142 + cx->dec = & rc2_DecryptCBC; 1.143 + LOAD(cx->iv.s); 1.144 + } else { 1.145 + cx->enc = & rc2_EncryptECB; 1.146 + cx->dec = & rc2_DecryptECB; 1.147 + } 1.148 + 1.149 + /* Step 0. Copy key into table. */ 1.150 + memcpy(cx->B, key, len); 1.151 + 1.152 + /* Step 1. Compute all values to the right of the key. */ 1.153 + L2 = cx->B; 1.154 + L = L2 + len; 1.155 + tmpB = L[-1]; 1.156 + for (i = (sizeof cx->B) - len; i > 0; --i) { 1.157 + *L++ = tmpB = S[ (PRUint8)(tmpB + *L2++) ]; 1.158 + } 1.159 + 1.160 + /* step 2. Adjust left most byte of effective key. */ 1.161 + i = (sizeof cx->B) - efLen8; 1.162 + L = cx->B + i; 1.163 + *L = tmpB = S[*L]; /* mask is always 0xff */ 1.164 + 1.165 + /* step 3. Recompute all values to the left of effective key. */ 1.166 + L2 = --L + efLen8; 1.167 + while(L >= cx->B) { 1.168 + *L-- = tmpB = S[ tmpB ^ *L2-- ]; 1.169 + } 1.170 + 1.171 +#if !defined(IS_LITTLE_ENDIAN) 1.172 + for (i = 63; i >= 0; --i) { 1.173 + SWAPK(i); /* candidate for unrolling */ 1.174 + } 1.175 +#endif 1.176 + return SECSuccess; 1.177 +} 1.178 + 1.179 +/* 1.180 +** Create a new RC2 context suitable for RC2 encryption/decryption. 1.181 +** "key" raw key data 1.182 +** "len" the number of bytes of key data 1.183 +** "iv" is the CBC initialization vector (if mode is NSS_RC2_CBC) 1.184 +** "mode" one of NSS_RC2 or NSS_RC2_CBC 1.185 +** "effectiveKeyLen" in bytes, not bits. 1.186 +** 1.187 +** When mode is set to NSS_RC2_CBC the RC2 cipher is run in "cipher block 1.188 +** chaining" mode. 1.189 +*/ 1.190 +RC2Context * 1.191 +RC2_CreateContext(const unsigned char *key, unsigned int len, 1.192 + const unsigned char *iv, int mode, unsigned efLen8) 1.193 +{ 1.194 + RC2Context *cx = PORT_ZNew(RC2Context); 1.195 + if (cx) { 1.196 + SECStatus rv = RC2_InitContext(cx, key, len, iv, mode, efLen8, 0); 1.197 + if (rv != SECSuccess) { 1.198 + RC2_DestroyContext(cx, PR_TRUE); 1.199 + cx = NULL; 1.200 + } 1.201 + } 1.202 + return cx; 1.203 +} 1.204 + 1.205 +/* 1.206 +** Destroy an RC2 encryption/decryption context. 1.207 +** "cx" the context 1.208 +** "freeit" if PR_TRUE then free the object as well as its sub-objects 1.209 +*/ 1.210 +void 1.211 +RC2_DestroyContext(RC2Context *cx, PRBool freeit) 1.212 +{ 1.213 + if (cx) { 1.214 + memset(cx, 0, sizeof *cx); 1.215 + if (freeit) { 1.216 + PORT_Free(cx); 1.217 + } 1.218 + } 1.219 +} 1.220 + 1.221 +#define ROL(x,k) (x << k | x >> (16-k)) 1.222 +#define MIX(j) \ 1.223 + R0 = R0 + cx->K[ 4*j+0] + (R3 & R2) + (~R3 & R1); R0 = ROL(R0,1);\ 1.224 + R1 = R1 + cx->K[ 4*j+1] + (R0 & R3) + (~R0 & R2); R1 = ROL(R1,2);\ 1.225 + R2 = R2 + cx->K[ 4*j+2] + (R1 & R0) + (~R1 & R3); R2 = ROL(R2,3);\ 1.226 + R3 = R3 + cx->K[ 4*j+3] + (R2 & R1) + (~R2 & R0); R3 = ROL(R3,5) 1.227 +#define MASH \ 1.228 + R0 = R0 + cx->K[R3 & 63];\ 1.229 + R1 = R1 + cx->K[R0 & 63];\ 1.230 + R2 = R2 + cx->K[R1 & 63];\ 1.231 + R3 = R3 + cx->K[R2 & 63] 1.232 + 1.233 +/* Encrypt one block */ 1.234 +static void 1.235 +rc2_Encrypt1Block(RC2Context *cx, RC2Block *output, RC2Block *input) 1.236 +{ 1.237 + register PRUint16 R0, R1, R2, R3; 1.238 + 1.239 + /* step 1. Initialize input. */ 1.240 + R0 = input->s[0]; 1.241 + R1 = input->s[1]; 1.242 + R2 = input->s[2]; 1.243 + R3 = input->s[3]; 1.244 + 1.245 + /* step 2. Expand Key (already done, in context) */ 1.246 + /* step 3. j = 0 */ 1.247 + /* step 4. Perform 5 mixing rounds. */ 1.248 + 1.249 + MIX(0); 1.250 + MIX(1); 1.251 + MIX(2); 1.252 + MIX(3); 1.253 + MIX(4); 1.254 + 1.255 + /* step 5. Perform 1 mashing round. */ 1.256 + MASH; 1.257 + 1.258 + /* step 6. Perform 6 mixing rounds. */ 1.259 + 1.260 + MIX(5); 1.261 + MIX(6); 1.262 + MIX(7); 1.263 + MIX(8); 1.264 + MIX(9); 1.265 + MIX(10); 1.266 + 1.267 + /* step 7. Perform 1 mashing round. */ 1.268 + MASH; 1.269 + 1.270 + /* step 8. Perform 5 mixing rounds. */ 1.271 + 1.272 + MIX(11); 1.273 + MIX(12); 1.274 + MIX(13); 1.275 + MIX(14); 1.276 + MIX(15); 1.277 + 1.278 + /* output results */ 1.279 + output->s[0] = R0; 1.280 + output->s[1] = R1; 1.281 + output->s[2] = R2; 1.282 + output->s[3] = R3; 1.283 +} 1.284 + 1.285 +#define ROR(x,k) (x >> k | x << (16-k)) 1.286 +#define R_MIX(j) \ 1.287 + R3 = ROR(R3,5); R3 = R3 - cx->K[ 4*j+3] - (R2 & R1) - (~R2 & R0); \ 1.288 + R2 = ROR(R2,3); R2 = R2 - cx->K[ 4*j+2] - (R1 & R0) - (~R1 & R3); \ 1.289 + R1 = ROR(R1,2); R1 = R1 - cx->K[ 4*j+1] - (R0 & R3) - (~R0 & R2); \ 1.290 + R0 = ROR(R0,1); R0 = R0 - cx->K[ 4*j+0] - (R3 & R2) - (~R3 & R1) 1.291 +#define R_MASH \ 1.292 + R3 = R3 - cx->K[R2 & 63];\ 1.293 + R2 = R2 - cx->K[R1 & 63];\ 1.294 + R1 = R1 - cx->K[R0 & 63];\ 1.295 + R0 = R0 - cx->K[R3 & 63] 1.296 + 1.297 +/* Encrypt one block */ 1.298 +static void 1.299 +rc2_Decrypt1Block(RC2Context *cx, RC2Block *output, RC2Block *input) 1.300 +{ 1.301 + register PRUint16 R0, R1, R2, R3; 1.302 + 1.303 + /* step 1. Initialize input. */ 1.304 + R0 = input->s[0]; 1.305 + R1 = input->s[1]; 1.306 + R2 = input->s[2]; 1.307 + R3 = input->s[3]; 1.308 + 1.309 + /* step 2. Expand Key (already done, in context) */ 1.310 + /* step 3. j = 63 */ 1.311 + /* step 4. Perform 5 r_mixing rounds. */ 1.312 + R_MIX(15); 1.313 + R_MIX(14); 1.314 + R_MIX(13); 1.315 + R_MIX(12); 1.316 + R_MIX(11); 1.317 + 1.318 + /* step 5. Perform 1 r_mashing round. */ 1.319 + R_MASH; 1.320 + 1.321 + /* step 6. Perform 6 r_mixing rounds. */ 1.322 + R_MIX(10); 1.323 + R_MIX(9); 1.324 + R_MIX(8); 1.325 + R_MIX(7); 1.326 + R_MIX(6); 1.327 + R_MIX(5); 1.328 + 1.329 + /* step 7. Perform 1 r_mashing round. */ 1.330 + R_MASH; 1.331 + 1.332 + /* step 8. Perform 5 r_mixing rounds. */ 1.333 + R_MIX(4); 1.334 + R_MIX(3); 1.335 + R_MIX(2); 1.336 + R_MIX(1); 1.337 + R_MIX(0); 1.338 + 1.339 + /* output results */ 1.340 + output->s[0] = R0; 1.341 + output->s[1] = R1; 1.342 + output->s[2] = R2; 1.343 + output->s[3] = R3; 1.344 +} 1.345 + 1.346 +static SECStatus 1.347 +rc2_EncryptECB(RC2Context *cx, unsigned char *output, 1.348 + const unsigned char *input, unsigned int inputLen) 1.349 +{ 1.350 + RC2Block iBlock; 1.351 + 1.352 + while (inputLen > 0) { 1.353 + LOAD(iBlock.s) 1.354 + rc2_Encrypt1Block(cx, &iBlock, &iBlock); 1.355 + STORE(iBlock.s) 1.356 + output += RC2_BLOCK_SIZE; 1.357 + input += RC2_BLOCK_SIZE; 1.358 + inputLen -= RC2_BLOCK_SIZE; 1.359 + } 1.360 + return SECSuccess; 1.361 +} 1.362 + 1.363 +static SECStatus 1.364 +rc2_DecryptECB(RC2Context *cx, unsigned char *output, 1.365 + const unsigned char *input, unsigned int inputLen) 1.366 +{ 1.367 + RC2Block iBlock; 1.368 + 1.369 + while (inputLen > 0) { 1.370 + LOAD(iBlock.s) 1.371 + rc2_Decrypt1Block(cx, &iBlock, &iBlock); 1.372 + STORE(iBlock.s) 1.373 + output += RC2_BLOCK_SIZE; 1.374 + input += RC2_BLOCK_SIZE; 1.375 + inputLen -= RC2_BLOCK_SIZE; 1.376 + } 1.377 + return SECSuccess; 1.378 +} 1.379 + 1.380 +static SECStatus 1.381 +rc2_EncryptCBC(RC2Context *cx, unsigned char *output, 1.382 + const unsigned char *input, unsigned int inputLen) 1.383 +{ 1.384 + RC2Block iBlock; 1.385 + 1.386 + while (inputLen > 0) { 1.387 + 1.388 + LOAD(iBlock.s) 1.389 + iBlock.l[0] ^= cx->iv.l[0]; 1.390 + iBlock.l[1] ^= cx->iv.l[1]; 1.391 + rc2_Encrypt1Block(cx, &iBlock, &iBlock); 1.392 + cx->iv = iBlock; 1.393 + STORE(iBlock.s) 1.394 + output += RC2_BLOCK_SIZE; 1.395 + input += RC2_BLOCK_SIZE; 1.396 + inputLen -= RC2_BLOCK_SIZE; 1.397 + } 1.398 + return SECSuccess; 1.399 +} 1.400 + 1.401 +static SECStatus 1.402 +rc2_DecryptCBC(RC2Context *cx, unsigned char *output, 1.403 + const unsigned char *input, unsigned int inputLen) 1.404 +{ 1.405 + RC2Block iBlock; 1.406 + RC2Block oBlock; 1.407 + 1.408 + while (inputLen > 0) { 1.409 + LOAD(iBlock.s) 1.410 + rc2_Decrypt1Block(cx, &oBlock, &iBlock); 1.411 + oBlock.l[0] ^= cx->iv.l[0]; 1.412 + oBlock.l[1] ^= cx->iv.l[1]; 1.413 + cx->iv = iBlock; 1.414 + STORE(oBlock.s) 1.415 + output += RC2_BLOCK_SIZE; 1.416 + input += RC2_BLOCK_SIZE; 1.417 + inputLen -= RC2_BLOCK_SIZE; 1.418 + } 1.419 + return SECSuccess; 1.420 +} 1.421 + 1.422 + 1.423 +/* 1.424 +** Perform RC2 encryption. 1.425 +** "cx" the context 1.426 +** "output" the output buffer to store the encrypted data. 1.427 +** "outputLen" how much data is stored in "output". Set by the routine 1.428 +** after some data is stored in output. 1.429 +** "maxOutputLen" the maximum amount of data that can ever be 1.430 +** stored in "output" 1.431 +** "input" the input data 1.432 +** "inputLen" the amount of input data 1.433 +*/ 1.434 +SECStatus RC2_Encrypt(RC2Context *cx, unsigned char *output, 1.435 + unsigned int *outputLen, unsigned int maxOutputLen, 1.436 + const unsigned char *input, unsigned int inputLen) 1.437 +{ 1.438 + SECStatus rv = SECSuccess; 1.439 + if (inputLen) { 1.440 + if (inputLen % RC2_BLOCK_SIZE) { 1.441 + PORT_SetError(SEC_ERROR_INPUT_LEN); 1.442 + return SECFailure; 1.443 + } 1.444 + if (maxOutputLen < inputLen) { 1.445 + PORT_SetError(SEC_ERROR_OUTPUT_LEN); 1.446 + return SECFailure; 1.447 + } 1.448 + rv = (*cx->enc)(cx, output, input, inputLen); 1.449 + } 1.450 + if (rv == SECSuccess) { 1.451 + *outputLen = inputLen; 1.452 + } 1.453 + return rv; 1.454 +} 1.455 + 1.456 +/* 1.457 +** Perform RC2 decryption. 1.458 +** "cx" the context 1.459 +** "output" the output buffer to store the decrypted data. 1.460 +** "outputLen" how much data is stored in "output". Set by the routine 1.461 +** after some data is stored in output. 1.462 +** "maxOutputLen" the maximum amount of data that can ever be 1.463 +** stored in "output" 1.464 +** "input" the input data 1.465 +** "inputLen" the amount of input data 1.466 +*/ 1.467 +SECStatus RC2_Decrypt(RC2Context *cx, unsigned char *output, 1.468 + unsigned int *outputLen, unsigned int maxOutputLen, 1.469 + const unsigned char *input, unsigned int inputLen) 1.470 +{ 1.471 + SECStatus rv = SECSuccess; 1.472 + if (inputLen) { 1.473 + if (inputLen % RC2_BLOCK_SIZE) { 1.474 + PORT_SetError(SEC_ERROR_INPUT_LEN); 1.475 + return SECFailure; 1.476 + } 1.477 + if (maxOutputLen < inputLen) { 1.478 + PORT_SetError(SEC_ERROR_OUTPUT_LEN); 1.479 + return SECFailure; 1.480 + } 1.481 + rv = (*cx->dec)(cx, output, input, inputLen); 1.482 + } 1.483 + if (rv == SECSuccess) { 1.484 + *outputLen = inputLen; 1.485 + } 1.486 + return rv; 1.487 +} 1.488 +