]>
Commit | Line | Data |
---|---|---|
d8f41ccd | 1 | /* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
2 | * |
3 | * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT | |
4 | * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE | |
d8f41ccd A |
5 | * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE |
6 | * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE, | |
b1ab9ed8 A |
7 | * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL |
8 | * EXPOSE YOU TO LIABILITY. | |
9 | *************************************************************************** | |
10 | * | |
11 | * byteRep.c - FEE portable byte representation support | |
12 | * | |
13 | * Revision History | |
14 | * ---------------- | |
15 | * 10/06/98 ap | |
16 | * Changed to compile with C++. | |
d8f41ccd | 17 | * 18 Apr 98 at Apple |
b1ab9ed8 | 18 | * Mods for variable size giantDigit. |
d8f41ccd | 19 | * 20 Jan 98 at Apple |
b1ab9ed8 | 20 | * Added curve param fields for CURVE_PARAM_VERSION 2. |
d8f41ccd | 21 | * 17 Jul 97 at Apple |
b1ab9ed8 | 22 | * Added signature routines. |
d8f41ccd | 23 | * 9 Jan 97 at NeXT |
b1ab9ed8 A |
24 | * Split off from utilities.c |
25 | */ | |
26 | ||
27 | #include "byteRep.h" | |
28 | #include "feeTypes.h" | |
29 | #include "curveParams.h" | |
30 | #include "giantIntegers.h" | |
31 | #include "elliptic.h" | |
32 | #include "falloc.h" | |
33 | #include "ckutilities.h" | |
34 | #include "feeDebug.h" | |
35 | #include <stdlib.h> | |
36 | ||
37 | #ifndef NULL | |
38 | #define NULL ((void *)0) | |
39 | #endif /* NULL */ | |
40 | ||
41 | /* | |
42 | * Support for portable bytestream representation of keys and signatures. | |
43 | * Platform and endianness independent; format shared with JavaFEE | |
44 | * implementation. | |
45 | */ | |
46 | ||
47 | /* | |
48 | * Some handy macros. | |
49 | */ | |
50 | #define ENC_BYTE(n, b, bytes) \ | |
51 | *b++ = n; \ | |
52 | bytes++; | |
53 | ||
54 | #define ENC_INT(n, b, bytes, i) \ | |
55 | i = intToByteRep(n, b); \ | |
56 | bytes += i; \ | |
57 | b += i; | |
58 | ||
59 | #define ENC_GIANT(g, b, bytes, i) \ | |
60 | i = giantToByteRep(g, b); \ | |
61 | bytes += i; \ | |
62 | b += i; | |
63 | ||
64 | #define DEC_BYTE(n, b, blen, bytes) \ | |
65 | n = *b++; \ | |
66 | bytes++; \ | |
67 | blen--; | |
68 | ||
69 | #define DEC_INT(n, b, blen, bytes) \ | |
70 | n = byteRepToInt(b); \ | |
71 | b += sizeof(int); \ | |
72 | bytes += sizeof(int); \ | |
73 | blen -= gLen; | |
74 | ||
75 | #define DEC_GIANT(g, b, blen, glen, bytes, out) \ | |
76 | g = byteRepToGiant(b, blen, &glen); \ | |
77 | if(g == NULL) { \ | |
78 | goto out; \ | |
79 | } \ | |
80 | b += glen; \ | |
81 | bytes += glen; \ | |
82 | blen -= gLen; | |
83 | ||
84 | ||
85 | ||
86 | ||
87 | /* | |
88 | * The routines which convert various types to byte reps return the number | |
89 | * of bytes written to the output stream. | |
90 | */ | |
91 | int intToByteRep(int i, unsigned char *buf) | |
92 | { | |
93 | *buf++ = (unsigned char)((i >> 24) & 0xff); | |
94 | *buf++ = (unsigned char)((i >> 16) & 0xff); | |
95 | *buf++ = (unsigned char)((i >> 8) & 0xff); | |
96 | *buf = (unsigned char)(i & 0xff); | |
97 | return 4; | |
98 | } | |
99 | ||
100 | int shortToByteRep(short s, unsigned char *buf) | |
101 | { | |
102 | *buf++ = (unsigned char)((s >> 8) & 0xff); | |
103 | *buf = (unsigned char)(s & 0xff); | |
104 | return 2; | |
105 | } | |
106 | ||
107 | /* | |
108 | * 7 Apr 1998 : leading int is now the number of bytes in the giant's | |
109 | * giantDigits array. This value is signed. | |
110 | */ | |
111 | int giantToByteRep(giant g, unsigned char *buf) | |
112 | { | |
113 | int numBytes = g->sign * GIANT_BYTES_PER_DIGIT; | |
114 | unsigned aNumBytes = abs(numBytes); | |
115 | ||
116 | CKASSERT(g != NULL); | |
117 | intToByteRep(numBytes, buf); | |
118 | buf += sizeof(int); | |
119 | serializeGiant(g, buf, aNumBytes); | |
120 | return (sizeof(int) + aNumBytes); | |
121 | } | |
122 | ||
123 | int keyToByteRep(key k, unsigned char *buf) | |
124 | { | |
125 | int numBytes = 0; | |
126 | int i; | |
127 | ||
128 | CKASSERT(k != NULL); | |
129 | ENC_GIANT(k->x, buf, numBytes, i); | |
130 | ||
131 | /* only write y for plus curve */ | |
132 | if(k->twist == CURVE_PLUS) { | |
133 | CKASSERT(k->y != NULL); | |
134 | ENC_GIANT(k->y, buf, numBytes, i); | |
135 | } | |
136 | return numBytes; | |
137 | } | |
138 | ||
139 | #define CURVE_PARAM_VERSION 3 | |
140 | #define CURVE_PARAM_VERSION_MIN 3 | |
141 | ||
142 | int curveParamsToByteRep(curveParams *cp, unsigned char *buf) | |
143 | { | |
144 | int numBytes = 0; | |
145 | int i; | |
146 | ||
147 | CKASSERT(cp != NULL); | |
148 | ENC_INT(CURVE_PARAM_VERSION, buf, numBytes, i); | |
149 | ENC_INT(CURVE_PARAM_VERSION_MIN, buf, numBytes, i); | |
150 | ENC_BYTE(cp->primeType, buf, numBytes); | |
151 | ENC_BYTE(cp->curveType, buf, numBytes); | |
152 | ENC_INT(cp->q, buf, numBytes, i); | |
153 | ENC_INT(cp->k, buf, numBytes, i); | |
154 | ENC_INT(cp->m, buf, numBytes, i); | |
155 | ENC_INT(0, buf, numBytes, i); // spare | |
156 | ||
157 | ENC_GIANT(cp->a, buf, numBytes, i); | |
158 | ENC_GIANT(cp->b, buf, numBytes, i); | |
159 | ENC_GIANT(cp->c, buf, numBytes, i); | |
160 | ENC_GIANT(cp->x1Plus, buf, numBytes, i); | |
161 | ENC_GIANT(cp->x1Minus, buf, numBytes, i); | |
162 | ENC_GIANT(cp->cOrderPlus, buf, numBytes, i); | |
163 | ENC_GIANT(cp->cOrderMinus, buf, numBytes, i); | |
164 | ENC_GIANT(cp->x1OrderPlus, buf, numBytes, i); | |
165 | ENC_GIANT(cp->x1OrderMinus, buf, numBytes, i); | |
166 | if(cp->primeType == FPT_General) { | |
167 | ENC_GIANT(cp->basePrime, buf, numBytes, i); | |
168 | } | |
169 | return numBytes; | |
170 | } | |
171 | ||
172 | int sigToByteRep(int magic, | |
173 | int version, | |
174 | int minVersion, | |
175 | giant g0, | |
176 | giant g1, | |
177 | unsigned char *buf) | |
178 | { | |
179 | int numBytes = 0; | |
180 | int i; | |
181 | ||
182 | ENC_INT(magic, buf, numBytes, i); | |
183 | ENC_INT(version, buf, numBytes, i); | |
184 | ENC_INT(minVersion, buf, numBytes, i); | |
185 | ENC_INT(0, buf, numBytes, i); // spare | |
186 | ENC_GIANT(g0, buf, numBytes, i); | |
187 | ENC_GIANT(g1, buf, numBytes, i); | |
188 | ||
189 | return numBytes; | |
190 | } | |
191 | ||
192 | ||
193 | /* | |
194 | * return the size of various data types' byte representations. | |
195 | */ | |
196 | int lengthOfByteRepGiant(giant g) | |
197 | { | |
198 | CKASSERT(g != NULL); | |
199 | return sizeof(int) + (GIANT_BYTES_PER_DIGIT * abs(g->sign)); | |
200 | } | |
201 | ||
202 | int lengthOfByteRepKey(key k) | |
203 | { | |
204 | int len = lengthOfByteRepGiant(k->x); | |
205 | ||
206 | CKASSERT(k != NULL); | |
207 | if(k->twist == CURVE_PLUS) { | |
208 | CKASSERT(k->y != NULL); | |
209 | len += lengthOfByteRepGiant(k->y); | |
210 | } | |
211 | return len; | |
212 | } | |
213 | ||
214 | int lengthOfByteRepCurveParams(curveParams *cp) | |
215 | { | |
216 | int length; | |
217 | ||
218 | CKASSERT(cp != NULL); | |
219 | length = (6 * sizeof(int)) + // ver, minVers, q, k, m, spare | |
220 | 2 + // primeType + curveType | |
221 | lengthOfByteRepGiant(cp->a) + | |
222 | lengthOfByteRepGiant(cp->b) + | |
223 | lengthOfByteRepGiant(cp->c) + | |
224 | lengthOfByteRepGiant(cp->x1Plus) + | |
225 | lengthOfByteRepGiant(cp->x1Minus) + | |
226 | lengthOfByteRepGiant(cp->cOrderPlus) + | |
227 | lengthOfByteRepGiant(cp->cOrderMinus) + | |
228 | lengthOfByteRepGiant(cp->x1OrderPlus) + | |
229 | lengthOfByteRepGiant(cp->x1OrderMinus); | |
230 | if(cp->primeType == FPT_General) { | |
231 | length += lengthOfByteRepGiant(cp->basePrime); | |
232 | } | |
233 | return length; | |
234 | } | |
235 | ||
236 | int lengthOfByteRepSig(giant g0, | |
237 | giant g1) | |
238 | { | |
239 | int length = (4 * sizeof(int)) + // magic, version, minVersion, | |
240 | // spare | |
241 | lengthOfByteRepGiant(g0) + | |
242 | lengthOfByteRepGiant(g1); | |
243 | return length; | |
244 | } | |
245 | ||
246 | /* | |
247 | * Routine to cons up various types from a byte rep stream. | |
248 | */ | |
249 | int byteRepToInt(const unsigned char *buf) { | |
250 | int result; | |
251 | ||
252 | result = (((int)buf[0] << 24) & 0xff000000) | | |
253 | (((int)buf[1] << 16) & 0x00ff0000) | | |
254 | (((int)buf[2] << 8) & 0xff00) | | |
255 | (((int)buf[3]) & 0xff); | |
256 | return result; | |
257 | } | |
258 | ||
259 | unsigned short byteRepToShort(const unsigned char *buf) { | |
260 | unsigned short result; | |
261 | ||
262 | result = (((unsigned short)buf[0] << 8) & 0xff00) | | |
263 | (((unsigned short)buf[1]) & 0xff); | |
264 | return result; | |
265 | } | |
266 | ||
267 | /* | |
268 | * Probably need byteRepToShortArray... | |
269 | */ | |
270 | ||
271 | /* | |
272 | * byte rep stream to giant. Returns NULL on error; returns number of bytes | |
273 | * of *buf snarfed in *giantLen if successful. | |
274 | * | |
275 | * 7 Apr 1998 : leading int is now the number of bytes in the giant's | |
276 | * giantDigits array. This value is signed. | |
277 | */ | |
278 | giant byteRepToGiant(const unsigned char *buf, | |
279 | unsigned bufLen, | |
280 | unsigned *giantLen) | |
281 | { | |
282 | giant g; | |
283 | int numDigits; | |
284 | int numBytes; // signed! | |
285 | unsigned aNumBytes; | |
286 | ||
287 | if(bufLen < sizeof(int)) { | |
288 | return (giant)NULL; | |
289 | } | |
290 | numBytes = byteRepToInt(buf); | |
291 | aNumBytes = abs(numBytes); | |
292 | numDigits = BYTES_TO_GIANT_DIGITS(aNumBytes); | |
293 | buf += sizeof(int); | |
294 | bufLen -= sizeof(int); | |
295 | if(numDigits > MAX_DIGITS) { | |
296 | return (giant)NULL; | |
297 | } | |
298 | ||
299 | if(bufLen < aNumBytes) { | |
300 | return (giant)NULL; | |
301 | } | |
302 | ||
303 | /* 9 Apr 1998 - sign = 0 means no following n[] bytes in the | |
304 | * byteRep. We do need to alloc one digit, in this case, though... | |
305 | * Note that the giantstruct has one implicit digit in n[]. | |
306 | */ | |
307 | if(aNumBytes == 0) { | |
308 | g = (giant)fmalloc(sizeof(giantstruct)); | |
309 | g->capacity = 1; | |
310 | } | |
311 | else { | |
312 | g = (giant)fmalloc(sizeof(giantstruct) + | |
313 | aNumBytes - GIANT_BYTES_PER_DIGIT); | |
314 | g->capacity = numDigits; | |
315 | } | |
316 | deserializeGiant(buf, g, aNumBytes); | |
317 | ||
318 | /* deserializeGiant always cooks up positive giant; sign is | |
319 | * properly trimmed to handle trailing (M.S.) zeroes. */ | |
320 | if(numBytes < 0) { | |
321 | g->sign = -g->sign; | |
322 | } | |
323 | *giantLen = sizeof(int) + aNumBytes; | |
324 | return g; | |
325 | ||
326 | } | |
327 | ||
328 | /* | |
329 | * Convert a byte stream (and some other parameters) into a | |
330 | * keystruct. | |
331 | * Returns NULL on error; returns number of bytes of *buf snarfed in | |
332 | * *keyLen if successful. | |
333 | */ | |
334 | key byteRepToKey(const unsigned char *buf, | |
335 | unsigned bufLen, | |
336 | int twist, | |
337 | curveParams *cp, | |
338 | unsigned *keyLen) // returned | |
339 | { | |
340 | key k; | |
341 | giant x; | |
342 | giant y; | |
343 | unsigned gLen; | |
344 | unsigned totalLen; | |
345 | ||
346 | x = byteRepToGiant(buf, bufLen, &gLen); | |
347 | if(x == NULL) { | |
348 | return NULL; | |
349 | } | |
350 | bufLen -= gLen; | |
351 | buf += gLen; | |
352 | totalLen = gLen; | |
353 | if(twist == CURVE_PLUS) { | |
354 | /* this also contains y */ | |
355 | y = byteRepToGiant(buf, bufLen, &gLen); | |
356 | if(y == NULL) { | |
357 | freeGiant(x); | |
358 | return NULL; | |
359 | } | |
360 | totalLen += gLen; | |
361 | } | |
362 | else { | |
363 | /* minus curve, y is not used */ | |
364 | y = newGiant(1); | |
365 | int_to_giant(0, y); | |
366 | } | |
367 | k = (key)fmalloc(sizeof(keystruct)); | |
368 | k->twist = twist; | |
369 | k->cp = cp; | |
370 | k->x = x; | |
371 | k->y = y; | |
372 | *keyLen = totalLen; | |
373 | return k; | |
374 | } | |
375 | ||
376 | curveParams *byteRepToCurveParams(const unsigned char *buf, | |
377 | unsigned bufLen, | |
378 | unsigned *cpLen) | |
379 | { | |
380 | curveParams *cp; | |
381 | unsigned gLen = 0; | |
382 | int version; | |
383 | int minVersion; | |
384 | int spare; | |
385 | int bytes = 0; | |
386 | ||
387 | if(bufLen < (5 * sizeof(int))) { // ver, minVers, q, k, spare | |
388 | return NULL; | |
389 | } | |
390 | cp = newCurveParams(); | |
391 | ||
392 | DEC_INT(version, buf, bufLen, bytes); | |
393 | DEC_INT(minVersion, buf, bufLen, bytes); | |
394 | if(minVersion > CURVE_PARAM_VERSION) { | |
395 | /* | |
396 | * Can't parse this; things have changed too much between | |
397 | * this version of the code and the time this curveParams | |
398 | * was written. | |
399 | */ | |
400 | goto abort; | |
401 | } | |
402 | ||
403 | DEC_BYTE(cp->primeType, buf, bufLen, bytes); | |
404 | DEC_BYTE(cp->curveType, buf, bufLen, bytes); | |
405 | DEC_INT(cp->q, buf, bufLen, bytes); | |
406 | DEC_INT(cp->k, buf, bufLen, bytes); | |
407 | DEC_INT(cp->m, buf, bufLen, bytes); | |
408 | DEC_INT(spare, buf, bufLen, bytes); | |
409 | ||
410 | DEC_GIANT(cp->a, buf, bufLen, gLen, bytes, abort); | |
411 | DEC_GIANT(cp->b, buf, bufLen, gLen, bytes, abort); | |
412 | DEC_GIANT(cp->c, buf, bufLen, gLen, bytes, abort); | |
413 | DEC_GIANT(cp->x1Plus, buf, bufLen, gLen, bytes, abort); | |
414 | DEC_GIANT(cp->x1Minus, buf, bufLen, gLen, bytes, abort); | |
415 | DEC_GIANT(cp->cOrderPlus, buf, bufLen, gLen, bytes, abort); | |
416 | DEC_GIANT(cp->cOrderMinus, buf, bufLen, gLen, bytes, abort); | |
417 | DEC_GIANT(cp->x1OrderPlus, buf, bufLen, gLen, bytes, abort); | |
418 | DEC_GIANT(cp->x1OrderMinus, buf, bufLen, gLen, bytes, abort); | |
419 | ||
420 | /* | |
421 | * basePrime only present in byte rep for PT_GENERAL | |
422 | */ | |
423 | if(cp->primeType == FPT_General) { | |
424 | DEC_GIANT(cp->basePrime, buf, bufLen, gLen, bytes, abort); | |
425 | } | |
426 | ||
427 | /* remaining fields inferred */ | |
428 | curveParamsInferFields(cp); | |
429 | allocRecipGiants(cp); | |
430 | ||
431 | *cpLen = bytes; | |
432 | return cp; | |
433 | ||
434 | abort: | |
435 | freeCurveParams(cp); | |
436 | return NULL; | |
437 | } | |
438 | ||
439 | /* | |
440 | * Returns 0 if bad format, e.g., if minVersion of sig is > than codeVersion. | |
441 | */ | |
442 | int byteRepToSig(const unsigned char *buf, | |
443 | unsigned bufLen, | |
444 | int codeVersion, | |
445 | int *sigMagic, // RETURNED | |
446 | int *sigVersion, // RETURNED | |
447 | int *sigMinVersion, // RETURNED | |
448 | giant *g0, // alloc'd & RETURNED | |
449 | giant *g1) // alloc'd & RETURNED | |
450 | { | |
451 | unsigned gLen = 0; | |
452 | int spare; | |
453 | int bytes = 0; | |
454 | ||
455 | if(bufLen < (4 * sizeof(int))) { // magic, version, minVersion, | |
456 | // spare | |
457 | return 0; | |
458 | } | |
459 | DEC_INT(*sigMagic, buf, bufLen, bytes); | |
460 | DEC_INT(*sigVersion, buf, bufLen, bytes); | |
461 | DEC_INT(*sigMinVersion, buf, bufLen, bytes); | |
462 | if(*sigMinVersion > codeVersion) { | |
463 | return 0; | |
464 | } | |
465 | DEC_INT(spare, buf, bufLen, bytes); | |
466 | // deleted 2/20/01 DEC_INT(*signerLen, buf, bufLen, bytes); | |
467 | // deleted 2/20/01 *signer = byteRepToUnichars(buf, *signerLen); | |
468 | // deleted 2/20/01 buf += (2 * *signerLen); | |
469 | // deleted 2/20/01 bufLen -= (2 * *signerLen); | |
470 | DEC_GIANT(*g0, buf, bufLen, gLen, bytes, abort); | |
471 | DEC_GIANT(*g1, buf, bufLen, gLen, bytes, abort); | |
472 | ||
473 | return 1; | |
474 | abort: | |
475 | return 0; | |
476 | } |