/* * Simple projective multiply. * * pt := pt * k, result normalized. */ void ellMulProjSimple(pointProj pt0, giant k, curveParams *cp) { pointProjStruct pt1; // local, giants borrowed CKASSERT(isone(pt0->z)); CKASSERT(cp->curveType == FCT_Weierstrass); /* ellMulProj assumes constant pt0, can't pass as src and dst */ pt1.x = borrowGiant(cp->maxDigits); pt1.y = borrowGiant(cp->maxDigits); pt1.z = borrowGiant(cp->maxDigits); ellMulProj(pt0, &pt1, k, cp); normalizeProj(&pt1, cp); CKASSERT(isone(pt1.z)); ptopProj(&pt1, pt0); returnGiant(pt1.x); returnGiant(pt1.y); returnGiant(pt1.z); }
feeReturn feeECDSAVerify(const unsigned char *sigData, size_t sigDataLen, const unsigned char *data, unsigned dataLen, feePubKey pubKey, feeSigFormat format) { /* giant integers per IEEE P1363 notation */ giant h; // s^(-1) giant h1; // f h giant h2; // c times h giant littleC; // newGiant from ECDSA_decode giant littleD; // ditto giant c; // borrowed, full size giant d; // ditto giant cPrime = NULL; // i mod r pointProj h1G = NULL; // h1 'o' G pointProj h2W = NULL; // h2 'o' W key W; // i.e., their public key unsigned version; feeReturn frtn; curveParams *cp = feePubKeyCurveParams(pubKey); unsigned groupBytesLen = ((feePubKeyBitsize(pubKey)+7) / 8); int result; if(cp == NULL) { return FR_BadPubKey; } /* * First decode the byteRep string. */ frtn = ECDSA_decode( format, groupBytesLen, sigData, sigDataLen, &littleC, &littleD, &version); if(frtn) { return frtn; } /* * littleC and littleD have capacity = abs(sign), probably * not big enough.... */ c = borrowGiant(cp->maxDigits); d = borrowGiant(cp->maxDigits); gtog(littleC, c); gtog(littleD, d); freeGiant(littleC); freeGiant(littleD); sigDbg(("ECDSA verify:\n")); /* * Verify that c and d are within [1,group_order-1] */ if((gcompg(cp->cOrderPlus, c) != 1) || (gcompg(cp->cOrderPlus, d) != 1) || isZero(c) || isZero(d)) { returnGiant(c); returnGiant(d); return FR_InvalidSignature; } /* * W = signer's public key */ W = feePubKeyPlusCurve(pubKey); /* * 1) Compute h = d^(-1) (mod x1OrderPlus); */ SIGPROF_START; h = borrowGiant(cp->maxDigits); gtog(d, h); binvg_x1OrderPlus(cp, h); SIGPROF_END(vfyStep1); /* * 2) h1 = digest as giant (skips assigning to 'f' in P1363) */ if(dataLen > (cp->maxDigits * GIANT_BYTES_PER_DIGIT)) { h1 = borrowGiant(BYTES_TO_GIANT_DIGITS(dataLen)); } else { h1 = borrowGiant(cp->maxDigits); } deserializeGiant(data, h1, dataLen); /* * Certicom SEC1 states that if the digest is larger than the modulus, * use the left q bits of the digest. */ unsigned hashBits = dataLen * 8; if(hashBits > cp->q) { gshiftright(hashBits - cp->q, h1); } sigLogGiant(" Wx : ", W->x); sigLogGiant(" f : ", h1); sigLogGiant(" c : ", c); sigLogGiant(" d : ", d); sigLogGiant(" s^(-1) : ", h); /* * 3) Compute h1 = f * h mod x1OrderPlus; */ SIGPROF_START; mulg(h, h1); // h1 := f * h x1OrderPlusMod(h1, cp); SIGPROF_END(vfyStep3); /* * 4) Compute h2 = c * h (mod x1OrderPlus); */ SIGPROF_START; h2 = borrowGiant(cp->maxDigits); gtog(c, h2); mulg(h, h2); // h2 := c * h x1OrderPlusMod(h2, cp); SIGPROF_END(vfyStep4); /* * 5) Compute h2W = h2 'o' W (W = theirPub) */ CKASSERT((W->y != NULL) && !isZero(W->y)); h2W = newPointProj(cp->maxDigits); gtog(W->x, h2W->x); gtog(W->y, h2W->y); int_to_giant(1, h2W->z); ellMulProjSimple(h2W, h2, cp); /* * 6) Compute h1G = h1 'o' G (G = {x1Plus, y1Plus, 1} ) */ CKASSERT((cp->y1Plus != NULL) && !isZero(cp->y1Plus)); h1G = newPointProj(cp->maxDigits); gtog(cp->x1Plus, h1G->x); gtog(cp->y1Plus, h1G->y); int_to_giant(1, h1G->z); ellMulProjSimple(h1G, h1, cp); /* * 7) h1G := (h1 'o' G) + (h2 'o' W) */ ellAddProj(h1G, h2W, cp); /* * 8) If elliptic sum is point at infinity, signature is bad; stop. */ if(isZero(h1G->z)) { dbgLog(("feeECDSAVerify: h1 * G = point at infinity\n")); result = 1; goto vfyDone; } normalizeProj(h1G, cp); /* * 9) cPrime = x coordinate of elliptic sum, mod x1OrderPlus */ cPrime = borrowGiant(cp->maxDigits); gtog(h1G->x, cPrime); x1OrderPlusMod(cPrime, cp); /* * 10) Good sig iff cPrime == c */ result = gcompg(c, cPrime); vfyDone: if(result) { frtn = FR_InvalidSignature; #if LOG_BAD_SIG printf("***yup, bad sig***\n"); #endif // LOG_BAD_SIG } else { frtn = FR_Success; } returnGiant(c); returnGiant(d); returnGiant(h); returnGiant(h1); returnGiant(h2); if(h1G != NULL) { freePointProj(h1G); } if(h2W != NULL) { freePointProj(h2W); } if(cPrime != NULL) { returnGiant(cPrime); } return frtn; }