]>
git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cryptkit/lib/feeECDSA.c
1 /* Copyright (c) 1998,2011,2014 Apple Inc. All Rights Reserved.
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 ***************************************************************************
11 * feeECDSA.c - Elliptic Curve Digital Signature Algorithm (per IEEE 1363)
16 * Added ECDSA_VERIFY_ONLY dependencies.
18 * Changed to compile with C++.
20 * Rewrote using projective elliptic algebra, per IEEE P1363.
22 * Fixed c==0 bug in feeECDSAVerify()
27 Nomenclature, per IEEE P1363 D1, Dec. 1997
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)
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:
46 d = [u^(-1) (f + (s*c))] (mod x1OrderPlus)
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].
52 Note: therefore a component of the signature could be slightly
53 larger than base prime.
55 Verification algorithm, given signature (c, d):
57 1) Compute h = d^(-1) (mod x1OrderPlus);
58 2) Compute h1 = digest as giant integer (skips assigning to 'f' as in
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.
73 #if CRYPTKIT_ECDSA_ENABLE
76 #include "feePublicKey.h"
77 #include "feePublicKeyPrivate.h"
78 #include "giantIntegers.h"
80 #include "feeRandom.h"
81 #include "curveParams.h"
83 #include "ckutilities.h"
90 #include "feeDigitalSignature.h"
91 #include "ECDSA_Profile.h"
92 #include "ellipticProj.h"
93 #if CRYPTKIT_DER_ENABLE
94 #include "CryptKitDER.h"
97 #ifndef ECDSA_VERIFY_ONLY
98 static void ECDSA_encode(
99 feeSigFormat format
, // Signature format DER 9.62 / RAW
100 unsigned groupBytesLen
,
103 unsigned char **sigData
, // malloc'd and RETURNED
104 unsigned *sigDataLen
); // RETURNED
105 #endif /* ECDSA_VERIFY_ONLY */
107 static feeReturn
ECDSA_decode(
108 feeSigFormat format
, // Signature format DER 9.62 / RAW
109 unsigned groupBytesLen
,
110 const unsigned char *sigData
,
112 giant
*gs
, // alloc'd & RETURNED
113 giant
*x0
, // alloc'd & RETURNED
114 unsigned *sigVersion
); // RETURNED
117 #define ECDSA_DEBUG 0
119 int ecdsaDebug
=1; /* tweakable at runtime via debugger */
124 #define sigLogGiant(s, g) \
127 printGiant(g) /*printGiantExp(g)*/; \
131 #define sigLogGiant(s, g)
132 #endif // ECDSA_DEBUG
136 * Profiling accumulators.
151 #endif // ECDSA_PROFILE
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().
158 #define FEE_ECDSA_VERSION 2
159 #define FEE_ECDSA_VERSION_MIN 2
162 * When true, use ellMulProjSimple rather than elliptic_simple in
163 * sign operation. Using ellMulProjSimple is a *big* win.
165 #define ECDSA_SIGN_USE_PROJ 1
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.
173 #ifndef ECDSA_VERIFY_ONLY
175 feeReturn
feeECDSASign(
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
187 /* giant integers per IEEE P1363 notation */
189 giant c
; // both 1363 'c' and 'i'
190 // i.e., x-coord of u's pub key
192 giant u
; // random private key
193 giant s
; // private key as giant
194 giant f
; // data (message) as giant
196 feeReturn frtn
= FR_Success
;
198 unsigned char *randBytes
;
199 unsigned randBytesLen
;
200 unsigned groupBytesLen
;
202 #if ECDSA_SIGN_USE_PROJ
203 pointProjStruct pt
; // pt->x = c
206 #endif // ECDSA_SIGN_USE_PROJ
211 cp
= feePubKeyCurveParams(pubKey
);
215 if(cp
->curveType
!= FCT_Weierstrass
) {
216 return FR_IllegalCurve
;
219 CKASSERT(!isZero(cp
->x1OrderPlus
));
222 * Private key and message to be signed as giants
224 privGiant
= feePubKeyPrivData(pubKey
);
225 if(privGiant
== NULL
) {
226 dbgLog(("Attempt to Sign without private data\n"));
227 return FR_IllegalArg
;
229 s
= borrowGiant(cp
->maxDigits
);
231 if(dataLen
> (cp
->maxDigits
* GIANT_BYTES_PER_DIGIT
)) {
232 f
= borrowGiant(BYTES_TO_GIANT_DIGITS(dataLen
));
235 f
= borrowGiant(cp
->maxDigits
);
237 deserializeGiant(data
, f
, dataLen
);
240 * Certicom SEC1 states that if the digest is larger than the modulus,
241 * use the left q bits of the digest.
243 unsigned hashBits
= dataLen
* 8;
244 if(hashBits
> cp
->q
) {
245 gshiftright(hashBits
- cp
->q
, f
);
248 sigDbg(("ECDSA sign:\n"));
249 sigLogGiant(" s : ", s
);
250 sigLogGiant(" f : ", f
);
252 c
= borrowGiant(cp
->maxDigits
);
253 d
= borrowGiant(cp
->maxDigits
);
254 u
= borrowGiant(cp
->maxDigits
);
255 if(randFcn
== NULL
) {
256 frand
= feeRandAlloc();
263 * Random size is just larger than base prime
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
);
269 #if ECDSA_SIGN_USE_PROJ
270 /* quick temp pointProj */
271 pty
= borrowGiant(cp
->maxDigits
);
272 ptz
= borrowGiant(cp
->maxDigits
);
276 #endif // ECDSA_SIGN_USE_PROJ
279 /* Repeat this loop until we have a non-zero c and d */
282 * 1) Obtain random u in [2, x1OrderPlus-2]
286 randFcn(randRef
, randBytes
, randBytesLen
);
289 feeRandBytes(frand
, randBytes
, randBytesLen
);
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
);
299 * note 'o' indicates elliptic multiply, * is integer mult.
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);
308 #if ECDSA_SIGN_USE_PROJ
310 /* projective coordinates */
311 gtog(cp
->y1Plus
, pty
);
312 int_to_giant(1, ptz
);
313 ellMulProjSimple(&pt
, u
, cp
);
315 #else /* ECDSA_SIGN_USE_PROJ */
318 elliptic_simple(c
, u
, cp
);
320 #endif /* ECDSA_SIGN_USE_PROJ */
322 SIGPROF_END(signStep2
);
324 x1OrderPlusMod(c
, cp
);
325 SIGPROF_END(signStep34
);
327 dbgLog(("feeECDSASign: zero modulo (1)\n"));
332 * 5) Compute u^(-1) mod x1OrderPlus;
336 binvg_x1OrderPlus(cp
, d
);
337 SIGPROF_END(signStep5
);
338 sigLogGiant(" u^(-1) : ", d
);
341 * 6) Compute signature d as:
342 * d = [u^(-1) (f + s*c)] (mod x1OrderPlus)
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
);
354 * 7) If d = 0, goto (1);
357 dbgLog(("feeECDSASign: zero modulo (2)\n"));
360 sigLogGiant(" c : ", c
);
361 sigLogGiant(" d : ", d
);
362 break; // normal successful exit
366 * 8) signature is now the integer pair (c, d).
370 * Cook up raw data representing the signature.
373 ECDSA_encode(format
,groupBytesLen
, c
, d
, sigData
, sigDataLen
);
374 SIGPROF_END(signStep8
);
385 #if ECDSA_SIGN_USE_PROJ
388 #endif /* ECDSA_SIGN_USE_PROJ */
392 #endif /* ECDSA_VERIFY_ONLY */
395 * Verify signature for specified data (most likely a hash result) and
396 * feePubKey. Returns FR_Success or FR_InvalidSignature.
399 #define LOG_BAD_SIG 0
401 feeReturn
feeECDSAVerify(const unsigned char *sigData
,
403 const unsigned char *data
,
408 /* giant integers per IEEE P1363 notation */
411 giant h2
; // c times h
412 giant littleC
; // newGiant from ECDSA_decode
413 giant littleD
; // ditto
414 giant c
; // borrowed, full size
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
423 curveParams
*cp
= feePubKeyCurveParams(pubKey
);
424 unsigned groupBytesLen
= ((feePubKeyBitsize(pubKey
)+7) / 8);
432 * First decode the byteRep string.
447 * littleC and littleD have capacity = abs(sign), probably
450 c
= borrowGiant(cp
->maxDigits
);
451 d
= borrowGiant(cp
->maxDigits
);
457 sigDbg(("ECDSA verify:\n"));
460 * Verify that c and d are within [1,group_order-1]
462 if((gcompg(cp
->cOrderPlus
, c
) != 1) || (gcompg(cp
->cOrderPlus
, d
) != 1) ||
463 isZero(c
) || isZero(d
)) {
464 return FR_InvalidSignature
;
468 * W = signer's public key
470 W
= feePubKeyPlusCurve(pubKey
);
473 * 1) Compute h = d^(-1) (mod x1OrderPlus);
476 h
= borrowGiant(cp
->maxDigits
);
478 binvg_x1OrderPlus(cp
, h
);
479 SIGPROF_END(vfyStep1
);
482 * 2) h1 = digest as giant (skips assigning to 'f' in P1363)
484 if(dataLen
> (cp
->maxDigits
* GIANT_BYTES_PER_DIGIT
)) {
485 h1
= borrowGiant(BYTES_TO_GIANT_DIGITS(dataLen
));
488 h1
= borrowGiant(cp
->maxDigits
);
490 deserializeGiant(data
, h1
, dataLen
);
493 * Certicom SEC1 states that if the digest is larger than the modulus,
494 * use the left q bits of the digest.
496 unsigned hashBits
= dataLen
* 8;
497 if(hashBits
> cp
->q
) {
498 gshiftright(hashBits
- cp
->q
, h1
);
501 sigLogGiant(" Wx : ", W
->x
);
502 sigLogGiant(" f : ", h1
);
503 sigLogGiant(" c : ", c
);
504 sigLogGiant(" d : ", d
);
505 sigLogGiant(" s^(-1) : ", h
);
508 * 3) Compute h1 = f * h mod x1OrderPlus;
511 mulg(h
, h1
); // h1 := f * h
512 x1OrderPlusMod(h1
, cp
);
513 SIGPROF_END(vfyStep3
);
516 * 4) Compute h2 = c * h (mod x1OrderPlus);
519 h2
= borrowGiant(cp
->maxDigits
);
521 mulg(h
, h2
); // h2 := c * h
522 x1OrderPlusMod(h2
, cp
);
523 SIGPROF_END(vfyStep4
);
526 * 5) Compute h2W = h2 'o' W (W = theirPub)
528 CKASSERT((W
->y
!= NULL
) && !isZero(W
->y
));
529 h2W
= newPointProj(cp
->maxDigits
);
532 int_to_giant(1, h2W
->z
);
533 ellMulProjSimple(h2W
, h2
, cp
);
536 * 6) Compute h1G = h1 'o' G (G = {x1Plus, y1Plus, 1} )
538 CKASSERT((cp
->y1Plus
!= NULL
) && !isZero(cp
->y1Plus
));
539 h1G
= newPointProj(cp
->maxDigits
);
540 gtog(cp
->x1Plus
, h1G
->x
);
541 gtog(cp
->y1Plus
, h1G
->y
);
542 int_to_giant(1, h1G
->z
);
543 ellMulProjSimple(h1G
, h1
, cp
);
546 * 7) h1G := (h1 'o' G) + (h2 'o' W)
548 ellAddProj(h1G
, h2W
, cp
);
551 * 8) If elliptic sum is point at infinity, signature is bad; stop.
554 dbgLog(("feeECDSAVerify: h1 * G = point at infinity\n"));
558 normalizeProj(h1G
, cp
);
561 * 9) cPrime = x coordinate of elliptic sum, mod x1OrderPlus
563 cPrime
= borrowGiant(cp
->maxDigits
);
564 gtog(h1G
->x
, cPrime
);
565 x1OrderPlusMod(cPrime
, cp
);
568 * 10) Good sig iff cPrime == c
570 result
= gcompg(c
, cPrime
);
574 frtn
= FR_InvalidSignature
;
576 printf("***yup, bad sig***\n");
577 #endif // LOG_BAD_SIG
600 #ifndef ECDSA_VERIFY_ONLY
603 * Encode to/from byteRep.
605 static void ECDSA_encode(
606 feeSigFormat format
, // Signature format DER 9.62 / RAW
607 unsigned groupBytesLen
,
610 unsigned char **sigData
, // malloc'd and RETURNED
611 unsigned *sigDataLen
) // RETURNED
613 #if CRYPTKIT_DER_ENABLE
614 if (format
==FSF_RAW
) {
615 feeRAWEncodeECDSASignature(groupBytesLen
,c
, d
, sigData
, sigDataLen
);
617 feeDEREncodeECDSASignature(c
, d
, sigData
, sigDataLen
);
620 *sigDataLen
= lengthOfByteRepSig(c
, d
);
621 *sigData
= (unsigned char*) fmalloc(*sigDataLen
);
622 sigToByteRep(FEE_ECDSA_MAGIC
,
624 FEE_ECDSA_VERSION_MIN
,
631 #endif /* ECDSA_VERIFY_ONLY */
633 static feeReturn
ECDSA_decode(
634 feeSigFormat format
, // Signature format DER 9.62 / RAW
635 unsigned groupBytesLen
,
636 const unsigned char *sigData
,
638 giant
*c
, // alloc'd & RETURNED
639 giant
*d
, // alloc'd & RETURNED
640 unsigned *sigVersion
) // RETURNED
642 #if CRYPTKIT_DER_ENABLE
644 if (format
==FSF_RAW
) {
645 frtn
= feeRAWDecodeECDSASignature(groupBytesLen
, sigData
, sigDataLen
, c
, d
);
647 frtn
= feeDERDecodeECDSASignature(sigData
, sigDataLen
, c
, d
);
649 if(frtn
== FR_Success
) {
650 *sigVersion
= FEE_ECDSA_VERSION
;
658 rtn
= byteRepToSig(sigData
,
667 return FR_BadSignatureFormat
;
670 case FEE_ECDSA_MAGIC
:
672 case FEE_SIG_MAGIC
: // ElGamal sig!
673 return FR_WrongSignatureType
;
675 return FR_BadSignatureFormat
;
681 * For given key, calculate maximum signature size.
683 feeReturn
feeECDSASigSize(
687 /* For now, assume that c and d in the signature are
688 * same size as the key's associated curveParams->basePrime.
689 * We might have to pad this a bit....
691 curveParams
*cp
= feePubKeyCurveParams(pubKey
);
696 #if CRYPTKIT_DER_ENABLE
697 *maxSigLen
= feeSizeOfDERSig(cp
->basePrime
, cp
->basePrime
);
699 *maxSigLen
= (unsigned)lengthOfByteRepSig(cp
->basePrime
, cp
->basePrime
);
704 #endif /* CRYPTKIT_ECDSA_ENABLE */