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