Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Side by Side Diff: nss/lib/freebl/aeskeywrap.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « nss/lib/dev/nssdevt.h ('k') | nss/lib/freebl/alg2268.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * aeskeywrap.c - implement AES Key Wrap algorithm from RFC 3394
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 "prcpucfg.h"
13 #if defined(IS_LITTLE_ENDIAN) || defined(SHA_NO_LONG_LONG)
14 #define BIG_ENDIAN_WITH_64_BIT_REGISTERS 0
15 #else
16 #define BIG_ENDIAN_WITH_64_BIT_REGISTERS 1
17 #endif
18 #include "prtypes.h" /* for PRUintXX */
19 #include "secport.h" /* for PORT_XXX */
20 #include "secerr.h"
21 #include "blapi.h" /* for AES_ functions */
22 #include "rijndael.h"
23
24 struct AESKeyWrapContextStr {
25 unsigned char iv[AES_KEY_WRAP_IV_BYTES];
26 AESContext aescx;
27 };
28
29 /******************************************/
30 /*
31 ** AES key wrap algorithm, RFC 3394
32 */
33
34 AESKeyWrapContext *
35 AESKeyWrap_AllocateContext(void)
36 {
37 AESKeyWrapContext * cx = PORT_New(AESKeyWrapContext);
38 return cx;
39 }
40
41 SECStatus
42 AESKeyWrap_InitContext(AESKeyWrapContext *cx,
43 const unsigned char *key,
44 unsigned int keylen,
45 const unsigned char *iv,
46 int x1,
47 unsigned int encrypt,
48 unsigned int x2)
49 {
50 SECStatus rv = SECFailure;
51 if (!cx) {
52 PORT_SetError(SEC_ERROR_INVALID_ARGS);
53 return SECFailure;
54 }
55 if (iv) {
56 memcpy(cx->iv, iv, sizeof cx->iv);
57 } else {
58 memset(cx->iv, 0xA6, sizeof cx->iv);
59 }
60 rv = AES_InitContext(&cx->aescx, key, keylen, NULL, NSS_AES, encrypt,
61 AES_BLOCK_SIZE);
62 return rv;
63 }
64
65 /*
66 ** Create a new AES context suitable for AES encryption/decryption.
67 ** "key" raw key data
68 ** "keylen" the number of bytes of key data (16, 24, or 32)
69 */
70 extern AESKeyWrapContext *
71 AESKeyWrap_CreateContext(const unsigned char *key, const unsigned char *iv,
72 int encrypt, unsigned int keylen)
73 {
74 SECStatus rv;
75 AESKeyWrapContext * cx = AESKeyWrap_AllocateContext();
76 if (!cx)
77 return NULL; /* error is already set */
78 rv = AESKeyWrap_InitContext(cx, key, keylen, iv, 0, encrypt, 0);
79 if (rv != SECSuccess) {
80 PORT_Free(cx);
81 cx = NULL; /* error should already be set */
82 }
83 return cx;
84 }
85
86 /*
87 ** Destroy a AES KeyWrap context.
88 ** "cx" the context
89 ** "freeit" if PR_TRUE then free the object as well as its sub-objects
90 */
91 extern void
92 AESKeyWrap_DestroyContext(AESKeyWrapContext *cx, PRBool freeit)
93 {
94 if (cx) {
95 AES_DestroyContext(&cx->aescx, PR_FALSE);
96 /* memset(cx, 0, sizeof *cx); */
97 if (freeit)
98 PORT_Free(cx);
99 }
100 }
101
102 #if !BIG_ENDIAN_WITH_64_BIT_REGISTERS
103
104 /* The AES Key Wrap algorithm has 64-bit values that are ALWAYS big-endian
105 ** (Most significant byte first) in memory. The only ALU operations done
106 ** on them are increment, decrement, and XOR. So, on little-endian CPUs,
107 ** and on CPUs that lack 64-bit registers, these big-endian 64-bit operations
108 ** are simulated in the following code. This is thought to be faster and
109 ** simpler than trying to convert the data to little-endian and back.
110 */
111
112 /* A and T point to two 64-bit values stored most signficant byte first
113 ** (big endian). This function increments the 64-bit value T, and then
114 ** XORs it with A, changing A.
115 */
116 static void
117 increment_and_xor(unsigned char *A, unsigned char *T)
118 {
119 if (!++T[7])
120 if (!++T[6])
121 if (!++T[5])
122 if (!++T[4])
123 if (!++T[3])
124 if (!++T[2])
125 if (!++T[1])
126 ++T[0];
127
128 A[0] ^= T[0];
129 A[1] ^= T[1];
130 A[2] ^= T[2];
131 A[3] ^= T[3];
132 A[4] ^= T[4];
133 A[5] ^= T[5];
134 A[6] ^= T[6];
135 A[7] ^= T[7];
136 }
137
138 /* A and T point to two 64-bit values stored most signficant byte first
139 ** (big endian). This function XORs T with A, giving a new A, then
140 ** decrements the 64-bit value T.
141 */
142 static void
143 xor_and_decrement(unsigned char *A, unsigned char *T)
144 {
145 A[0] ^= T[0];
146 A[1] ^= T[1];
147 A[2] ^= T[2];
148 A[3] ^= T[3];
149 A[4] ^= T[4];
150 A[5] ^= T[5];
151 A[6] ^= T[6];
152 A[7] ^= T[7];
153
154 if (!T[7]--)
155 if (!T[6]--)
156 if (!T[5]--)
157 if (!T[4]--)
158 if (!T[3]--)
159 if (!T[2]--)
160 if (!T[1]--)
161 T[0]--;
162
163 }
164
165 /* Given an unsigned long t (in host byte order), store this value as a
166 ** 64-bit big-endian value (MSB first) in *pt.
167 */
168 static void
169 set_t(unsigned char *pt, unsigned long t)
170 {
171 pt[7] = (unsigned char)t; t >>= 8;
172 pt[6] = (unsigned char)t; t >>= 8;
173 pt[5] = (unsigned char)t; t >>= 8;
174 pt[4] = (unsigned char)t; t >>= 8;
175 pt[3] = (unsigned char)t; t >>= 8;
176 pt[2] = (unsigned char)t; t >>= 8;
177 pt[1] = (unsigned char)t; t >>= 8;
178 pt[0] = (unsigned char)t;
179 }
180
181 #endif
182
183 /*
184 ** Perform AES key wrap.
185 ** "cx" the context
186 ** "output" the output buffer to store the encrypted data.
187 ** "outputLen" how much data is stored in "output". Set by the routine
188 ** after some data is stored in output.
189 ** "maxOutputLen" the maximum amount of data that can ever be
190 ** stored in "output"
191 ** "input" the input data
192 ** "inputLen" the amount of input data
193 */
194 extern SECStatus
195 AESKeyWrap_Encrypt(AESKeyWrapContext *cx, unsigned char *output,
196 unsigned int *pOutputLen, unsigned int maxOutputLen,
197 const unsigned char *input, unsigned int inputLen)
198 {
199 PRUint64 * R = NULL;
200 unsigned int nBlocks;
201 unsigned int i, j;
202 unsigned int aesLen = AES_BLOCK_SIZE;
203 unsigned int outLen = inputLen + AES_KEY_WRAP_BLOCK_SIZE;
204 SECStatus s = SECFailure;
205 /* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
206 PRUint64 t;
207 PRUint64 B[2];
208
209 #define A B[0]
210
211 /* Check args */
212 if (!inputLen || 0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
213 PORT_SetError(SEC_ERROR_INPUT_LEN);
214 return s;
215 }
216 #ifdef maybe
217 if (!output && pOutputLen) { /* caller is asking for output size */
218 *pOutputLen = outLen;
219 return SECSuccess;
220 }
221 #endif
222 if (maxOutputLen < outLen) {
223 PORT_SetError(SEC_ERROR_OUTPUT_LEN);
224 return s;
225 }
226 if (cx == NULL || output == NULL || input == NULL) {
227 PORT_SetError(SEC_ERROR_INVALID_ARGS);
228 return s;
229 }
230 nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
231 R = PORT_NewArray(PRUint64, nBlocks + 1);
232 if (!R)
233 return s; /* error is already set. */
234 /*
235 ** 1) Initialize variables.
236 */
237 memcpy(&A, cx->iv, AES_KEY_WRAP_IV_BYTES);
238 memcpy(&R[1], input, inputLen);
239 #if BIG_ENDIAN_WITH_64_BIT_REGISTERS
240 t = 0;
241 #else
242 memset(&t, 0, sizeof t);
243 #endif
244 /*
245 ** 2) Calculate intermediate values.
246 */
247 for (j = 0; j < 6; ++j) {
248 for (i = 1; i <= nBlocks; ++i) {
249 B[1] = R[i];
250 s = AES_Encrypt(&cx->aescx, (unsigned char *)B, &aesLen,
251 sizeof B, (unsigned char *)B, sizeof B);
252 if (s != SECSuccess)
253 break;
254 R[i] = B[1];
255 /* here, increment t and XOR A with t (in big endian order); */
256 #if BIG_ENDIAN_WITH_64_BIT_REGISTERS
257 A ^= ++t;
258 #else
259 increment_and_xor((unsigned char *)&A, (unsigned char *)&t);
260 #endif
261 }
262 }
263 /*
264 ** 3) Output the results.
265 */
266 if (s == SECSuccess) {
267 R[0] = A;
268 memcpy(output, &R[0], outLen);
269 if (pOutputLen)
270 *pOutputLen = outLen;
271 } else if (pOutputLen) {
272 *pOutputLen = 0;
273 }
274 PORT_ZFree(R, outLen);
275 return s;
276 }
277 #undef A
278
279 /*
280 ** Perform AES key unwrap.
281 ** "cx" the context
282 ** "output" the output buffer to store the decrypted data.
283 ** "outputLen" how much data is stored in "output". Set by the routine
284 ** after some data is stored in output.
285 ** "maxOutputLen" the maximum amount of data that can ever be
286 ** stored in "output"
287 ** "input" the input data
288 ** "inputLen" the amount of input data
289 */
290 extern SECStatus
291 AESKeyWrap_Decrypt(AESKeyWrapContext *cx, unsigned char *output,
292 unsigned int *pOutputLen, unsigned int maxOutputLen,
293 const unsigned char *input, unsigned int inputLen)
294 {
295 PRUint64 * R = NULL;
296 unsigned int nBlocks;
297 unsigned int i, j;
298 unsigned int aesLen = AES_BLOCK_SIZE;
299 unsigned int outLen;
300 SECStatus s = SECFailure;
301 /* These PRUint64s are ALWAYS big endian, regardless of CPU orientation. */
302 PRUint64 t;
303 PRUint64 B[2];
304
305 #define A B[0]
306
307 /* Check args */
308 if (inputLen < 3 * AES_KEY_WRAP_BLOCK_SIZE ||
309 0 != inputLen % AES_KEY_WRAP_BLOCK_SIZE) {
310 PORT_SetError(SEC_ERROR_INPUT_LEN);
311 return s;
312 }
313 outLen = inputLen - AES_KEY_WRAP_BLOCK_SIZE;
314 #ifdef maybe
315 if (!output && pOutputLen) { /* caller is asking for output size */
316 *pOutputLen = outLen;
317 return SECSuccess;
318 }
319 #endif
320 if (maxOutputLen < outLen) {
321 PORT_SetError(SEC_ERROR_OUTPUT_LEN);
322 return s;
323 }
324 if (cx == NULL || output == NULL || input == NULL) {
325 PORT_SetError(SEC_ERROR_INVALID_ARGS);
326 return s;
327 }
328 nBlocks = inputLen / AES_KEY_WRAP_BLOCK_SIZE;
329 R = PORT_NewArray(PRUint64, nBlocks);
330 if (!R)
331 return s; /* error is already set. */
332 nBlocks--;
333 /*
334 ** 1) Initialize variables.
335 */
336 memcpy(&R[0], input, inputLen);
337 A = R[0];
338 #if BIG_ENDIAN_WITH_64_BIT_REGISTERS
339 t = 6UL * nBlocks;
340 #else
341 set_t((unsigned char *)&t, 6UL * nBlocks);
342 #endif
343 /*
344 ** 2) Calculate intermediate values.
345 */
346 for (j = 0; j < 6; ++j) {
347 for (i = nBlocks; i; --i) {
348 /* here, XOR A with t (in big endian order) and decrement t; */
349 #if BIG_ENDIAN_WITH_64_BIT_REGISTERS
350 A ^= t--;
351 #else
352 xor_and_decrement((unsigned char *)&A, (unsigned char *)&t);
353 #endif
354 B[1] = R[i];
355 s = AES_Decrypt(&cx->aescx, (unsigned char *)B, &aesLen,
356 sizeof B, (unsigned char *)B, sizeof B);
357 if (s != SECSuccess)
358 break;
359 R[i] = B[1];
360 }
361 }
362 /*
363 ** 3) Output the results.
364 */
365 if (s == SECSuccess) {
366 int bad = memcmp(&A, cx->iv, AES_KEY_WRAP_IV_BYTES);
367 if (!bad) {
368 memcpy(output, &R[1], outLen);
369 if (pOutputLen)
370 *pOutputLen = outLen;
371 } else {
372 s = SECFailure;
373 PORT_SetError(SEC_ERROR_BAD_DATA);
374 if (pOutputLen)
375 *pOutputLen = 0;
376 }
377 } else if (pOutputLen) {
378 *pOutputLen = 0;
379 }
380 PORT_ZFree(R, inputLen);
381 return s;
382 }
383 #undef A
OLDNEW
« no previous file with comments | « nss/lib/dev/nssdevt.h ('k') | nss/lib/freebl/alg2268.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698