Mercurial > trustbridge > nss-cmake-static
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 |