comparison nss/lib/freebl/alg2268.c @ 0:1e5118fa0cb1

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