]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cryptkit/lib/feeECDSA.c
Security-59306.11.20.tar.gz
[apple/security.git] / OSX / libsecurity_cryptkit / lib / feeECDSA.c
1 /* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved.
2 *
3 * NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
4 * TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
5 * SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE, INC. AND THE
6 * ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE,
7 * INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
8 * EXPOSE YOU TO LIABILITY.
9 ***************************************************************************
10 *
11 * feeECDSA.c - Elliptic Curve Digital Signature Algorithm (per IEEE 1363)
12 *
13 * Revision History
14 * ----------------
15 * 11/27/98 dmitch
16 * Added ECDSA_VERIFY_ONLY dependencies.
17 * 10/06/98 ap
18 * Changed to compile with C++.
19 * 3 Sep 98 at Apple
20 * Rewrote using projective elliptic algebra, per IEEE P1363.
21 * 17 Dec 97 at Apple
22 * Fixed c==0 bug in feeECDSAVerify()
23 * Created.
24 */
25
26 /****
27 Nomenclature, per IEEE P1363 D1, Dec. 1997
28
29 G = initial public point = (x1Plus, y1Plus) as usual
30 x1OrderPlus = IEEE r = (always prime) order of x1Plus
31 f = message to be signed, generally a SHA1 message digest
32 s = signer's private key
33 W = signer's public key
34 * : integer multiplication, as in (x * y)
35 'o' : elliptic multiply, as in (u 'o' G)
36
37 Signing algorithm:
38
39 1) Obtain random u in [2, x1OrderPlus-2];
40 2) Compute x coordinate, call it c, of u 'o' G (elliptic mul);
41 3) Reduce: c := c mod x1OrderPlus;
42 4) If c = 0, goto (1);
43 5) Compute u^(-1) (mod x1OrderPlus);
44 6) Compute signature s as:
45
46 d = [u^(-1) (f + (s*c))] (mod x1OrderPlus)
47
48 7) If d = 0, goto (1);
49 8) Signature is the integer pair (c, d). Each integer
50 in the pair must be in [1, x1OrderPlus-1].
51
52 Note: therefore a component of the signature could be slightly
53 larger than base prime.
54
55 Verification algorithm, given signature (c, d):
56
57 1) Compute h = d^(-1) (mod x1OrderPlus);
58 2) Compute h1 = digest as giant integer (skips assigning to 'f' as in
59 IEEE spec)
60 3) Compute h1 = h1 * h (mod x1OrderPlus) (i.e., = f * h)
61 4) Compute h2 = c * h (mod x1OrderPlus);
62 5) Compute h2W = h2 'o' W
63 6) Compute h1G = h1 'o' G
64 7) Compute elliptic sum of h1G + h2W
65 8) If elliptic sum is point at infinity, signature is bad; stop.
66 9) cPrime = x coordinate of elliptic sum, mod x1OrderPlus
67 10) Signature is good iff cPrime == c.
68
69 ***********/
70
71 #include "ckconfig.h"
72
73 #include "feeTypes.h"
74 #include "feePublicKey.h"
75 #include "feePublicKeyPrivate.h"
76 #include "giantIntegers.h"
77 #include "elliptic.h"
78 #include "feeRandom.h"
79 #include "curveParams.h"
80 #include "falloc.h"
81 #include "ckutilities.h"
82 #include "feeDebug.h"
83 #include "platform.h"
84 #include "byteRep.h"
85 #include <stdlib.h>
86 #include "feeECDSA.h"
87 #include "byteRep.h"
88 #include "feeDigitalSignature.h"
89 #include "ECDSA_Profile.h"
90 #include "ellipticProj.h"
91 #include "CryptKitDER.h"
92
93 #ifndef ECDSA_VERIFY_ONLY
94 static void ECDSA_encode(
95 feeSigFormat format, // Signature format DER 9.62 / RAW
96 unsigned groupBytesLen,
97 giant c,
98 giant d,
99 unsigned char **sigData, // malloc'd and RETURNED
100 unsigned *sigDataLen); // RETURNED
101 #endif /* ECDSA_VERIFY_ONLY */
102
103 static feeReturn ECDSA_decode(
104 feeSigFormat format, // Signature format DER 9.62 / RAW
105 unsigned groupBytesLen,
106 const unsigned char *sigData,
107 size_t sigDataLen,
108 giant *gs, // alloc'd & RETURNED
109 giant *x0, // alloc'd & RETURNED
110 unsigned *sigVersion); // RETURNED
111
112
113 #define ECDSA_DEBUG 0
114 #if ECDSA_DEBUG
115 int ecdsaDebug=1; /* tweakable at runtime via debugger */
116 #define sigDbg(x) \
117 if(ecdsaDebug) { \
118 printf x; \
119 }
120 #define sigLogGiant(s, g) \
121 if(ecdsaDebug) { \
122 printf(s); \
123 printGiant(g) /*printGiantExp(g)*/; \
124 }
125 #else // ECDSA_DEBUG
126 #define sigDbg(x)
127 #define sigLogGiant(s, g)
128 #endif // ECDSA_DEBUG
129
130 #if ECDSA_PROFILE
131 /*
132 * Profiling accumulators.
133 */
134 unsigned signStep1;
135 unsigned signStep2;
136 unsigned signStep34;
137 unsigned signStep5;
138 unsigned signStep67;
139 unsigned signStep8;
140 unsigned vfyStep1;
141 unsigned vfyStep3;
142 unsigned vfyStep4;
143 unsigned vfyStep5;
144 unsigned vfyStep6;
145 unsigned vfyStep7;
146 unsigned vfyStep8;
147 #endif // ECDSA_PROFILE
148
149 /*
150 * Totally incompatible with feeDigitalSignature.c. Caller must be aware of
151 * signature format. We will detect an ElGamal signature, however, and
152 * return FR_WrongSignatureType from feeECDSAVerify().
153 */
154 #define FEE_ECDSA_VERSION 2
155 #define FEE_ECDSA_VERSION_MIN 2
156
157 /*
158 * When true, use ellMulProjSimple rather than elliptic_simple in
159 * sign operation. Using ellMulProjSimple is a *big* win.
160 */
161 #define ECDSA_SIGN_USE_PROJ 1
162
163 /*
164 * Sign specified block of data (most likely a hash result) using
165 * specified private key. Result, an enc64-encoded signature block,
166 * is returned in *sigData.
167 */
168
169 #ifndef ECDSA_VERIFY_ONLY
170
171 feeReturn feeECDSASign(
172 feePubKey pubKey,
173 feeSigFormat format, // Signature format DER 9.62 / RAW
174 const unsigned char *data, // data to be signed
175 unsigned dataLen, // in bytes
176 feeRandFcn randFcn, // optional
177 void *randRef, // optional
178 unsigned char **sigData, // malloc'd and RETURNED
179 unsigned *sigDataLen) // RETURNED
180 {
181 curveParams *cp;
182
183 /* giant integers per IEEE P1363 notation */
184
185 giant c; // both 1363 'c' and 'i'
186 // i.e., x-coord of u's pub key
187 giant d;
188 giant u; // random private key
189 giant s; // private key as giant
190 giant f; // data (message) as giant
191
192 feeReturn frtn = FR_Success;
193 feeRand frand;
194 unsigned char *randBytes;
195 unsigned randBytesLen;
196 unsigned groupBytesLen;
197 giant privGiant;
198 #if ECDSA_SIGN_USE_PROJ
199 pointProjStruct pt; // pt->x = c
200 giant pty; // pt->y
201 giant ptz; // pt->z
202 #endif // ECDSA_SIGN_USE_PROJ
203
204 if(pubKey == NULL) {
205 return FR_BadPubKey;
206 }
207 cp = feePubKeyCurveParams(pubKey);
208 if(cp == NULL) {
209 return FR_BadPubKey;
210 }
211 if(cp->curveType != FCT_Weierstrass) {
212 return FR_IllegalCurve;
213 }
214
215 CKASSERT(!isZero(cp->x1OrderPlus));
216
217 /*
218 * Private key and message to be signed as giants
219 */
220 privGiant = feePubKeyPrivData(pubKey);
221 if(privGiant == NULL) {
222 dbgLog(("Attempt to Sign without private data\n"));
223 return FR_IllegalArg;
224 }
225 s = borrowGiant(cp->maxDigits);
226 gtog(privGiant, s);
227 if(dataLen > (cp->maxDigits * GIANT_BYTES_PER_DIGIT)) {
228 f = borrowGiant(BYTES_TO_GIANT_DIGITS(dataLen));
229 }
230 else {
231 f = borrowGiant(cp->maxDigits);
232 }
233 deserializeGiant(data, f, dataLen);
234
235 /*
236 * Certicom SEC1 states that if the digest is larger than the modulus,
237 * use the left q bits of the digest.
238 */
239 unsigned hashBits = dataLen * 8;
240 if(hashBits > cp->q) {
241 gshiftright(hashBits - cp->q, f);
242 }
243
244 sigDbg(("ECDSA sign:\n"));
245 sigLogGiant(" s : ", s);
246 sigLogGiant(" f : ", f);
247
248 c = borrowGiant(cp->maxDigits);
249 d = borrowGiant(cp->maxDigits);
250 u = borrowGiant(cp->maxDigits);
251 if(randFcn == NULL) {
252 frand = feeRandAlloc();
253 }
254 else {
255 frand = NULL;
256 }
257
258 /*
259 * Random size is just larger than base prime
260 */
261 groupBytesLen = ((feePubKeyBitsize(pubKey)+7) / 8);
262 randBytesLen = groupBytesLen+8; // +8bytes (64bits) to reduce the biais when with reduction mod prime. Per FIPS186-4 - "Using Extra Random Bits"
263 randBytes = (unsigned char*) fmalloc(randBytesLen);
264
265 #if ECDSA_SIGN_USE_PROJ
266 /* quick temp pointProj */
267 pty = borrowGiant(cp->maxDigits);
268 ptz = borrowGiant(cp->maxDigits);
269 pt.x = c;
270 pt.y = pty;
271 pt.z = ptz;
272 #endif // ECDSA_SIGN_USE_PROJ
273
274 while(1) {
275 /* Repeat this loop until we have a non-zero c and d */
276
277 /*
278 * 1) Obtain random u in [2, x1OrderPlus-2]
279 */
280 SIGPROF_START;
281 if(randFcn) {
282 randFcn(randRef, randBytes, randBytesLen);
283 }
284 else {
285 feeRandBytes(frand, randBytes, randBytesLen);
286 }
287 deserializeGiant(randBytes, u, randBytesLen);
288 sigLogGiant(" raw u : ", u);
289 sigLogGiant(" order : ", cp->x1OrderPlus);
290 x1OrderPlusJustify(u, cp);
291 SIGPROF_END(signStep1);
292 sigLogGiant(" in range u : ", u);
293
294 /*
295 * note 'o' indicates elliptic multiply, * is integer mult.
296 *
297 * 2) Compute x coordinate, call it c, of u 'o' G
298 * 3) Reduce: c := c mod x1OrderPlus;
299 * 4) If c == 0, goto (1);
300 */
301 SIGPROF_START;
302 gtog(cp->x1Plus, c);
303
304 #if ECDSA_SIGN_USE_PROJ
305
306 /* projective coordinates */
307 gtog(cp->y1Plus, pty);
308 int_to_giant(1, ptz);
309 ellMulProjSimple(&pt, u, cp);
310
311 #else /* ECDSA_SIGN_USE_PROJ */
312
313 /* the FEE way */
314 elliptic_simple(c, u, cp);
315
316 #endif /* ECDSA_SIGN_USE_PROJ */
317
318 SIGPROF_END(signStep2);
319 SIGPROF_START;
320 x1OrderPlusMod(c, cp);
321 SIGPROF_END(signStep34);
322 if(isZero(c)) {
323 dbgLog(("feeECDSASign: zero modulo (1)\n"));
324 continue;
325 }
326
327 /*
328 * 5) Compute u^(-1) mod x1OrderPlus;
329 */
330 SIGPROF_START;
331 gtog(u, d);
332 binvg_x1OrderPlus(cp, d);
333 SIGPROF_END(signStep5);
334 sigLogGiant(" u^(-1) : ", d);
335
336 /*
337 * 6) Compute signature d as:
338 * d = [u^(-1) (f + s*c)] (mod x1OrderPlus)
339 */
340 SIGPROF_START;
341 mulg(c, s); // s *= c
342 x1OrderPlusMod(s, cp);
343 addg(f, s); // s := f + (s * c)
344 x1OrderPlusMod(s, cp);
345 mulg(s, d); // d := u^(-1) (f + (s * c))
346 x1OrderPlusMod(d, cp);
347 SIGPROF_END(signStep67);
348
349 /*
350 * 7) If d = 0, goto (1);
351 */
352 if(isZero(d)) {
353 dbgLog(("feeECDSASign: zero modulo (2)\n"));
354 continue;
355 }
356 sigLogGiant(" c : ", c);
357 sigLogGiant(" d : ", d);
358 break; // normal successful exit
359 }
360
361 /*
362 * 8) signature is now the integer pair (c, d).
363 */
364
365 /*
366 * Cook up raw data representing the signature.
367 */
368 SIGPROF_START;
369 ECDSA_encode(format,groupBytesLen, c, d, sigData, sigDataLen);
370 SIGPROF_END(signStep8);
371
372 if(frand != NULL) {
373 feeRandFree(frand);
374 }
375 ffree(randBytes);
376 returnGiant(u);
377 returnGiant(d);
378 returnGiant(c);
379 returnGiant(f);
380 returnGiant(s);
381 #if ECDSA_SIGN_USE_PROJ
382 returnGiant(pty);
383 returnGiant(ptz);
384 #endif /* ECDSA_SIGN_USE_PROJ */
385 return frtn;
386 }
387
388 #endif /* ECDSA_VERIFY_ONLY */
389
390 /*
391 * Verify signature for specified data (most likely a hash result) and
392 * feePubKey. Returns FR_Success or FR_InvalidSignature.
393 */
394
395 #define LOG_BAD_SIG 0
396
397 feeReturn feeECDSAVerify(const unsigned char *sigData,
398 size_t sigDataLen,
399 const unsigned char *data,
400 unsigned dataLen,
401 feePubKey pubKey,
402 feeSigFormat format)
403 {
404 /* giant integers per IEEE P1363 notation */
405 giant h; // s^(-1)
406 giant h1; // f h
407 giant h2; // c times h
408 giant littleC; // newGiant from ECDSA_decode
409 giant littleD; // ditto
410 giant c; // borrowed, full size
411 giant d; // ditto
412 giant cPrime = NULL; // i mod r
413 pointProj h1G = NULL; // h1 'o' G
414 pointProj h2W = NULL; // h2 'o' W
415 key W; // i.e., their public key
416
417 unsigned version;
418 feeReturn frtn;
419 curveParams *cp = feePubKeyCurveParams(pubKey);
420 unsigned groupBytesLen = ((feePubKeyBitsize(pubKey)+7) / 8);
421 int result;
422
423 if(cp == NULL) {
424 return FR_BadPubKey;
425 }
426
427 /*
428 * First decode the byteRep string.
429 */
430 frtn = ECDSA_decode(
431 format,
432 groupBytesLen,
433 sigData,
434 sigDataLen,
435 &littleC,
436 &littleD,
437 &version);
438 if(frtn) {
439 return frtn;
440 }
441
442 /*
443 * littleC and littleD have capacity = abs(sign), probably
444 * not big enough....
445 */
446 c = borrowGiant(cp->maxDigits);
447 d = borrowGiant(cp->maxDigits);
448 gtog(littleC, c);
449 gtog(littleD, d);
450 freeGiant(littleC);
451 freeGiant(littleD);
452
453 sigDbg(("ECDSA verify:\n"));
454
455 /*
456 * Verify that c and d are within [1,group_order-1]
457 */
458 if((gcompg(cp->cOrderPlus, c) != 1) || (gcompg(cp->cOrderPlus, d) != 1) ||
459 isZero(c) || isZero(d))
460 {
461 returnGiant(c);
462 returnGiant(d);
463 return FR_InvalidSignature;
464 }
465
466 /*
467 * W = signer's public key
468 */
469 W = feePubKeyPlusCurve(pubKey);
470
471 /*
472 * 1) Compute h = d^(-1) (mod x1OrderPlus);
473 */
474 SIGPROF_START;
475 h = borrowGiant(cp->maxDigits);
476 gtog(d, h);
477 binvg_x1OrderPlus(cp, h);
478 SIGPROF_END(vfyStep1);
479
480 /*
481 * 2) h1 = digest as giant (skips assigning to 'f' in P1363)
482 */
483 if(dataLen > (cp->maxDigits * GIANT_BYTES_PER_DIGIT)) {
484 h1 = borrowGiant(BYTES_TO_GIANT_DIGITS(dataLen));
485 }
486 else {
487 h1 = borrowGiant(cp->maxDigits);
488 }
489 deserializeGiant(data, h1, dataLen);
490
491 /*
492 * Certicom SEC1 states that if the digest is larger than the modulus,
493 * use the left q bits of the digest.
494 */
495 unsigned hashBits = dataLen * 8;
496 if(hashBits > cp->q) {
497 gshiftright(hashBits - cp->q, h1);
498 }
499
500 sigLogGiant(" Wx : ", W->x);
501 sigLogGiant(" f : ", h1);
502 sigLogGiant(" c : ", c);
503 sigLogGiant(" d : ", d);
504 sigLogGiant(" s^(-1) : ", h);
505
506 /*
507 * 3) Compute h1 = f * h mod x1OrderPlus;
508 */
509 SIGPROF_START;
510 mulg(h, h1); // h1 := f * h
511 x1OrderPlusMod(h1, cp);
512 SIGPROF_END(vfyStep3);
513
514 /*
515 * 4) Compute h2 = c * h (mod x1OrderPlus);
516 */
517 SIGPROF_START;
518 h2 = borrowGiant(cp->maxDigits);
519 gtog(c, h2);
520 mulg(h, h2); // h2 := c * h
521 x1OrderPlusMod(h2, cp);
522 SIGPROF_END(vfyStep4);
523
524 /*
525 * 5) Compute h2W = h2 'o' W (W = theirPub)
526 */
527 CKASSERT((W->y != NULL) && !isZero(W->y));
528 h2W = newPointProj(cp->maxDigits);
529 gtog(W->x, h2W->x);
530 gtog(W->y, h2W->y);
531 int_to_giant(1, h2W->z);
532 ellMulProjSimple(h2W, h2, cp);
533
534 /*
535 * 6) Compute h1G = h1 'o' G (G = {x1Plus, y1Plus, 1} )
536 */
537 CKASSERT((cp->y1Plus != NULL) && !isZero(cp->y1Plus));
538 h1G = newPointProj(cp->maxDigits);
539 gtog(cp->x1Plus, h1G->x);
540 gtog(cp->y1Plus, h1G->y);
541 int_to_giant(1, h1G->z);
542 ellMulProjSimple(h1G, h1, cp);
543
544 /*
545 * 7) h1G := (h1 'o' G) + (h2 'o' W)
546 */
547 ellAddProj(h1G, h2W, cp);
548
549 /*
550 * 8) If elliptic sum is point at infinity, signature is bad; stop.
551 */
552 if(isZero(h1G->z)) {
553 dbgLog(("feeECDSAVerify: h1 * G = point at infinity\n"));
554 result = 1;
555 goto vfyDone;
556 }
557 normalizeProj(h1G, cp);
558
559 /*
560 * 9) cPrime = x coordinate of elliptic sum, mod x1OrderPlus
561 */
562 cPrime = borrowGiant(cp->maxDigits);
563 gtog(h1G->x, cPrime);
564 x1OrderPlusMod(cPrime, cp);
565
566 /*
567 * 10) Good sig iff cPrime == c
568 */
569 result = gcompg(c, cPrime);
570
571 vfyDone:
572 if(result) {
573 frtn = FR_InvalidSignature;
574 #if LOG_BAD_SIG
575 printf("***yup, bad sig***\n");
576 #endif // LOG_BAD_SIG
577 }
578 else {
579 frtn = FR_Success;
580 }
581
582 returnGiant(c);
583 returnGiant(d);
584 returnGiant(h);
585 returnGiant(h1);
586 returnGiant(h2);
587 if(h1G != NULL) {
588 freePointProj(h1G);
589 }
590 if(h2W != NULL) {
591 freePointProj(h2W);
592 }
593 if(cPrime != NULL) {
594 returnGiant(cPrime);
595 }
596 return frtn;
597 }
598
599 #ifndef ECDSA_VERIFY_ONLY
600
601 /*
602 * Encode to/from byteRep.
603 */
604 static void ECDSA_encode(
605 feeSigFormat format, // Signature format DER 9.62 / RAW
606 unsigned groupBytesLen,
607 giant c,
608 giant d,
609 unsigned char **sigData, // malloc'd and RETURNED
610 unsigned *sigDataLen) // RETURNED
611 {
612 if (format==FSF_RAW) {
613 feeRAWEncodeECDSASignature(groupBytesLen,c, d, sigData, sigDataLen);
614 } else {
615 feeDEREncodeECDSASignature(c, d, sigData, sigDataLen);
616 }
617 }
618
619 #endif /* ECDSA_VERIFY_ONLY */
620
621 static feeReturn ECDSA_decode(
622 feeSigFormat format, // Signature format DER 9.62 / RAW
623 unsigned groupBytesLen,
624 const unsigned char *sigData,
625 size_t sigDataLen,
626 giant *c, // alloc'd & RETURNED
627 giant *d, // alloc'd & RETURNED
628 unsigned *sigVersion) // RETURNED
629 {
630 feeReturn frtn;
631 if (format==FSF_RAW) {
632 frtn = feeRAWDecodeECDSASignature(groupBytesLen, sigData, sigDataLen, c, d);
633 } else {
634 frtn = feeDERDecodeECDSASignature(sigData, sigDataLen, c, d);
635 }
636 if(frtn == FR_Success) {
637 *sigVersion = FEE_ECDSA_VERSION;
638 }
639 return frtn;
640 }
641
642 /*
643 * For given key, calculate maximum signature size.
644 */
645 feeReturn feeECDSASigSize(
646 feePubKey pubKey,
647 unsigned *maxSigLen)
648 {
649 /* For now, assume that c and d in the signature are
650 * same size as the key's associated curveParams->basePrime.
651 * We might have to pad this a bit....
652 */
653 curveParams *cp = feePubKeyCurveParams(pubKey);
654
655 if(cp == NULL) {
656 return FR_BadPubKey;
657 }
658
659 *maxSigLen = feeSizeOfDERSig(cp->basePrime, cp->basePrime);
660 return FR_Success;
661 }
662
663