void ecFree(EcPoint *r) { //Release previsoulsy allocated resources mpiFree(&r->x); mpiFree(&r->y); mpiFree(&r->z); }
bool_t ecIsPointAffine(const EcDomainParameters *params, const EcPoint *s) { error_t error; Mpi t1; Mpi t2; //Initialize multiple precision integers mpiInit(&t1); mpiInit(&t2); //Compute t1 = (Sx^3 + a * Sx + b) mod p EC_CHECK(ecSqrMod(params, &t1, &s->x)); EC_CHECK(ecMulMod(params, &t1, &t1, &s->x)); EC_CHECK(ecMulMod(params, &t2, ¶ms->a, &s->x)); EC_CHECK(ecAddMod(params, &t1, &t1, &t2)); EC_CHECK(ecAddMod(params, &t1, &t1, ¶ms->b)); //Compute t2 = Sy^2 EC_CHECK(ecSqrMod(params, &t2, &s->y)); //Check whether the point is on the elliptic curve if(mpiComp(&t1, &t2)) error = ERROR_FAILURE; end: //Release multiple precision integers mpiFree(&t1); mpiFree(&t2); //Return TRUE if the affine point S is on the curve, else FALSE return error ? FALSE : TRUE; }
void ecFreeDomainParameters(EcDomainParameters *params) { //Release previsoulsy allocated resources mpiFree(¶ms->p); mpiFree(¶ms->a); mpiFree(¶ms->b); ecFree(¶ms->g); mpiFree(¶ms->q); }
void dhFreeParameters(DhParameters *params) { //Free multiple precision integers mpiFree(¶ms->p); mpiFree(¶ms->g); mpiFree(¶ms->xa); mpiFree(¶ms->ya); mpiFree(¶ms->yb); }
void dhFree(DhContext *context) { //Release Diffie-Hellman parameters mpiFree(&context->params.p); mpiFree(&context->params.g); //Release private and public values mpiFree(&context->xa); mpiFree(&context->ya); mpiFree(&context->yb); }
error_t rsadp(const RsaPrivateKey *key, const Mpi *c, Mpi *m) { error_t error; Mpi m1; Mpi m2; Mpi h; //The ciphertext representative c shall be between 0 and n - 1 if(mpiCompInt(c, 0) < 0 || mpiComp(c, &key->n) >= 0) return ERROR_OUT_OF_RANGE; //Initialize multiple-precision integers mpiInit(&m1); mpiInit(&m2); mpiInit(&h); //Use the Chinese remainder algorithm? if(key->n.size && key->p.size && key->q.size && key->dp.size && key->dq.size && key->qinv.size) { //Compute m1 = c ^ dP mod p MPI_CHECK(mpiExpMod(&m1, c, &key->dp, &key->p)); //Compute m2 = c ^ dQ mod q MPI_CHECK(mpiExpMod(&m2, c, &key->dq, &key->q)); //Let h = (m1 - m2) * qInv mod p MPI_CHECK(mpiSub(&h, &m1, &m2)); MPI_CHECK(mpiMulMod(&h, &h, &key->qinv, &key->p)); //Let m = m2 + q * h MPI_CHECK(mpiMul(m, &key->q, &h)); MPI_CHECK(mpiAdd(m, m, &m2)); } //Use modular exponentiation? else if(key->n.size && key->d.size) { //Let m = c ^ d mod n error = mpiExpMod(m, c, &key->d, &key->n); } //Invalid parameters? else { //Report an error error = ERROR_INVALID_PARAMETER; } end: //Free previously allocated memory mpiFree(&m1); mpiFree(&m2); mpiFree(&h); //Return status code return error; }
error_t dhCheckPublicKey(DhParameters *params, const Mpi *publicKey) { error_t error; Mpi a; //Initialize multiple precision integer mpiInit(&a); //Precompute p - 1 error = mpiSubInt(&a, ¶ms->p, 1); //Check status if(!error) { //Reject weak public values 1 and p - 1 if(mpiCompInt(publicKey, 1) <= 0) error = ERROR_ILLEGAL_PARAMETER; else if(mpiComp(publicKey, &a) >= 0) error = ERROR_ILLEGAL_PARAMETER; } //Free previously allocated resources mpiFree(&a); //Return status code return error; }
void rsaFreePrivateKey(RsaPrivateKey *key) { //Free multiple precision integers mpiFree(&key->n); mpiFree(&key->e); mpiFree(&key->d); mpiFree(&key->p); mpiFree(&key->q); mpiFree(&key->dp); mpiFree(&key->dq); mpiFree(&key->qinv); }
error_t ecAffinify(const EcDomainParameters *params, EcPoint *r, const EcPoint *s) { error_t error; Mpi a; Mpi b; //Point at the infinity? if(!mpiCompInt(&s->z, 0)) return ERROR_INVALID_PARAMETER; //Initialize multiple precision integers mpiInit(&a); mpiInit(&b); //Compute a = 1/Sz mod p MPI_CHECK(mpiInvMod(&a, &s->z, ¶ms->p)); //Set Rx = a^2 * Sx mod p EC_CHECK(ecSqrMod(params, &b, &a)); EC_CHECK(ecMulMod(params, &r->x, &b, &s->x)); //Set Ry = a^3 * Sy mod p EC_CHECK(ecMulMod(params, &b, &b, &a)); EC_CHECK(ecMulMod(params, &r->y, &b, &s->y)); //Set Rz = 1 MPI_CHECK(mpiSetValue(&r->z, 1)); end: //Release multiple precision integers mpiFree(&a); mpiFree(&b); //Return status code return error; }
error_t dhComputeSharedSecret(DhContext *context, uint8_t *output, size_t outputSize, size_t *outputLength) { error_t error; size_t k; Mpi z; //Debug message TRACE_DEBUG("Computing Diffie-Hellman shared secret...\r\n"); //Get the length in octets of the prime modulus k = mpiGetByteLength(&context->params.p); //Make sure that the output buffer is large enough if(outputSize < k) return ERROR_INVALID_LENGTH; //The multiple precision integer must be initialized before it can be used mpiInit(&z); //Start of exception handling block do { //Calculate the shared secret key (k = yb ^ xa mod p) error = mpiExpMod(&z, &context->yb, &context->xa, &context->params.p); //Any error to report? if(error) return error; //Convert the resulting integer to an octet string error = mpiWriteRaw(&z, output, k); //Conversion failed? if(error) return error; //Length of the resulting shared secret *outputLength = k; //Debug message TRACE_DEBUG(" Shared secret (%" PRIuSIZE " bytes):\r\n", *outputLength); TRACE_DEBUG_ARRAY(" ", output, *outputLength); //End of exception handling block } while(0); //Release previously allocated resources mpiFree(&z); //Return status code return error; }
void rsaFreePublicKey(RsaPublicKey *key) { //Free multiple precision integers mpiFree(&key->n); mpiFree(&key->e); }
error_t rsassaPkcs1v15Verify(const RsaPublicKey *key, const HashAlgo *hash, const uint8_t *digest, const uint8_t *signature, size_t signatureLength) { error_t error; uint_t k; uint8_t *em; const uint8_t *oid; size_t oidLength; const uint8_t *d; size_t dLength; Mpi s; Mpi m; //Check parameters if(key == NULL || hash == NULL || digest == NULL || signature == NULL) return ERROR_INVALID_PARAMETER; //Debug message TRACE_DEBUG("RSA PKCS #1 v1.5 signature verification...\r\n"); TRACE_DEBUG(" Modulus:\r\n"); TRACE_DEBUG_MPI(" ", &key->n); TRACE_DEBUG(" Public exponent:\r\n"); TRACE_DEBUG_MPI(" ", &key->e); TRACE_DEBUG(" Message digest:\r\n"); TRACE_DEBUG_ARRAY(" ", digest, hash->digestSize); TRACE_DEBUG(" Signature:\r\n"); TRACE_DEBUG_ARRAY(" ", signature, signatureLength); //Initialize multiple-precision integers mpiInit(&s); mpiInit(&m); //Get the length in octets of the modulus n k = mpiGetByteLength(&key->n); //Check the length of the signature if(signatureLength != k) return ERROR_INVALID_LENGTH; //Allocate a memory buffer to hold the encoded message em = osAllocMem(k); //Failed to allocate memory? if(!em) return ERROR_OUT_OF_MEMORY; //Start of exception handling block do { //Convert the signature to an integer signature representative s error = mpiReadRaw(&s, signature, signatureLength); //Conversion failed? if(error) break; //Apply the RSAVP1 verification primitive error = rsavp1(key, &s, &m); //Any error to report? if(error) break; //Convert the message representative m to an encoded message EM of length k octets error = mpiWriteRaw(&m, em, k); //Conversion failed? if(error) break; //Debug message TRACE_DEBUG(" Encoded message\r\n"); TRACE_DEBUG_ARRAY(" ", em, k); //Parse the encoded message EM error = emsaPkcs1v15Decode(em, k, &oid, &oidLength, &d, &dLength); //Any error to report? if(error) break; //Assume an error... error = ERROR_INVALID_SIGNATURE_ALGO; //Ensure the hash algorithm identifier matches the OID if(oidComp(oid, oidLength, hash->oid, hash->oidSize)) break; //Check the length of the digest if(dLength != hash->digestSize) break; //Compare the message digest error = memcmp(digest, d, dLength) ? ERROR_INVALID_SIGNATURE : NO_ERROR; //End of exception handling block } while(0); //Release multiple precision integers mpiFree(&s); mpiFree(&m); //Free previously allocated memory osFreeMem(em); //Return status code return error; }
error_t rsassaPkcs1v15Sign(const RsaPrivateKey *key, const HashAlgo *hash, const uint8_t *digest, uint8_t *signature, size_t *signatureLength) { error_t error; uint_t k; uint8_t *em; Mpi m; Mpi s; //Check parameters if(key == NULL || hash == NULL || digest == NULL) return ERROR_INVALID_PARAMETER; if(signature == NULL || signatureLength == NULL) return ERROR_INVALID_PARAMETER; //Debug message TRACE_DEBUG("RSA PKCS #1 v1.5 signature generation...\r\n"); TRACE_DEBUG(" Modulus:\r\n"); TRACE_DEBUG_MPI(" ", &key->n); TRACE_DEBUG(" Public exponent:\r\n"); TRACE_DEBUG_MPI(" ", &key->e); TRACE_DEBUG(" Private exponent:\r\n"); TRACE_DEBUG_MPI(" ", &key->d); TRACE_DEBUG(" Prime 1:\r\n"); TRACE_DEBUG_MPI(" ", &key->p); TRACE_DEBUG(" Prime 2:\r\n"); TRACE_DEBUG_MPI(" ", &key->q); TRACE_DEBUG(" Prime exponent 1:\r\n"); TRACE_DEBUG_MPI(" ", &key->dp); TRACE_DEBUG(" Prime exponent 2:\r\n"); TRACE_DEBUG_MPI(" ", &key->dq); TRACE_DEBUG(" Coefficient:\r\n"); TRACE_DEBUG_MPI(" ", &key->qinv); TRACE_DEBUG(" Message digest:\r\n"); TRACE_DEBUG_ARRAY(" ", digest, hash->digestSize); //Initialize multiple-precision integers mpiInit(&m); mpiInit(&s); //Get the length in octets of the modulus n k = mpiGetByteLength(&key->n); //Point to the buffer where the encoded message EM will be generated em = signature; //Apply the EMSA-PKCS1-v1.5 encoding operation error = emsaPkcs1v15Encode(hash, digest, em, k); //Any error to report? if(error) return error; //Debug message TRACE_DEBUG(" Encoded message\r\n"); TRACE_DEBUG_ARRAY(" ", em, k); //Start of exception handling block do { //Convert the encoded message EM to an integer message representative m error = mpiReadRaw(&m, em, k); //Conversion failed? if(error) break; //Apply the RSASP1 signature primitive error = rsasp1(key, &m, &s); //Any error to report? if(error) break; //Convert the signature representative s to a signature of length k octets error = mpiWriteRaw(&s, signature, k); //Conversion failed? if(error) break; //Length of the resulting signature *signatureLength = k; //Debug message TRACE_DEBUG(" Signature:\r\n"); TRACE_DEBUG_ARRAY(" ", signature, *signatureLength); //End of exception handling block } while(0); //Free previously allocated memory mpiFree(&m); mpiFree(&s); //Return status code return error; }
error_t rsaesPkcs1v15Decrypt(const RsaPrivateKey *key, const uint8_t *ciphertext, size_t ciphertextLength, uint8_t *message, size_t messageSize, size_t *messageLength) { error_t error; uint_t i; uint_t k; uint8_t *em; Mpi c; Mpi m; //Check parameters if(key == NULL || ciphertext == NULL) return ERROR_INVALID_PARAMETER; if(message == NULL || messageLength == NULL) return ERROR_INVALID_PARAMETER; //Debug message TRACE_DEBUG("RSA PKCS #1 v1.5 decryption...\r\n"); TRACE_DEBUG(" Modulus:\r\n"); TRACE_DEBUG_MPI(" ", &key->n); TRACE_DEBUG(" Public exponent:\r\n"); TRACE_DEBUG_MPI(" ", &key->e); TRACE_DEBUG(" Private exponent:\r\n"); TRACE_DEBUG_MPI(" ", &key->d); TRACE_DEBUG(" Prime 1:\r\n"); TRACE_DEBUG_MPI(" ", &key->p); TRACE_DEBUG(" Prime 2:\r\n"); TRACE_DEBUG_MPI(" ", &key->q); TRACE_DEBUG(" Prime exponent 1:\r\n"); TRACE_DEBUG_MPI(" ", &key->dp); TRACE_DEBUG(" Prime exponent 2:\r\n"); TRACE_DEBUG_MPI(" ", &key->dq); TRACE_DEBUG(" Coefficient:\r\n"); TRACE_DEBUG_MPI(" ", &key->qinv); TRACE_DEBUG(" Ciphertext:\r\n"); TRACE_DEBUG_ARRAY(" ", ciphertext, ciphertextLength); //Initialize multiple-precision integers mpiInit(&c); mpiInit(&m); //Get the length in octets of the modulus n k = mpiGetByteLength(&key->n); //Check the length of the ciphertext if(ciphertextLength != k || ciphertextLength < 11) return ERROR_INVALID_LENGTH; //Allocate a buffer to store the encoded message EM em = osAllocMem(k); //Failed to allocate memory? if(!em) return ERROR_OUT_OF_MEMORY; //Start of exception handling block do { //Convert the ciphertext to an integer ciphertext representative c error = mpiReadRaw(&c, ciphertext, ciphertextLength); //Conversion failed? if(error) break; //Apply the RSADP decryption primitive error = rsadp(key, &c, &m); //Any error to report? if(error) break; //Convert the message representative m to an encoded message EM of length k octets error = mpiWriteRaw(&m, em, k); //Conversion failed? if(error) break; //Debug message TRACE_DEBUG(" Encoded message\r\n"); TRACE_DEBUG_ARRAY(" ", em, k); //The first octet of EM must have a value of 0x00 //and the block type BT shall be 0x02 if(em[0] != 0x00 || em[1] != 0x02) { //Report an error error = ERROR_UNEXPECTED_VALUE; break; } //An octet with hexadecimal value 0x00 is used to separate PS from M for(i = 2; i < k && em[i] != 0x00; i++); //Check whether the padding string is valid if(i < 10 || i >= k) { //Report an error error = ERROR_INVALID_PADDING; break; } //Ensure that the output buffer is large enough if(messageSize < (k - i - 1)) { //Report an error error = ERROR_INVALID_LENGTH; break; } //Recover the length of the message *messageLength = k - i - 1; //Copy the message contents memcpy(message, em + i + 1, *messageLength); //Debug message TRACE_DEBUG(" Message:\r\n"); TRACE_DEBUG_ARRAY(" ", message, *messageLength); //End of exception handling block } while(0); //Release multiple precision integers mpiFree(&c); mpiFree(&m); //Free previously allocated memory osFreeMem(em); //Return status code return error; }
error_t rsaesPkcs1v15Encrypt(const PrngAlgo *prngAlgo, void *prngContext, const RsaPublicKey *key, const uint8_t *message, size_t messageLength, uint8_t *ciphertext, size_t *ciphertextLength) { error_t error; uint_t i; uint_t j; uint_t k; uint_t n; uint8_t *p; Mpi m; Mpi c; //Check parameters if(key == NULL || message == NULL) return ERROR_INVALID_PARAMETER; if(ciphertext == NULL || ciphertextLength == NULL) return ERROR_INVALID_PARAMETER; //Debug message TRACE_DEBUG("RSA PKCS #1 v1.5 encryption...\r\n"); TRACE_DEBUG(" Modulus:\r\n"); TRACE_DEBUG_MPI(" ", &key->n); TRACE_DEBUG(" Public exponent:\r\n"); TRACE_DEBUG_MPI(" ", &key->e); TRACE_DEBUG(" Message:\r\n"); TRACE_DEBUG_ARRAY(" ", message, messageLength); //Initialize multiple-precision integers mpiInit(&m); mpiInit(&c); //Get the length in octets of the modulus n k = mpiGetByteLength(&key->n); //Check the length of the message if((messageLength + 11) > k) return ERROR_INVALID_LENGTH; //Point to the buffer where the encoded message EM will be formatted p = ciphertext; //The leading 0x00 octet ensures that the encoded message, //converted to an integer, is less than the modulus *(p++) = 0x00; //For a public-key operation, the block type BT shall be 0x02 *(p++) = 0x02; //Length of the padding string PS n = k - messageLength - 3; //Generate the padding string (pseudo-randomly generated non-zero octets) while(n > 0) { //Generate random data error = prngAlgo->read(prngContext, p, n); //Any error to report? if(error) return error; //Parse the resulting octet string for(i = 0, j = 0; j < n; j++) { //Strip any byte with a value of zero if(p[j] != 0) p[i++] = p[j]; } //Advance data pointer p += i; n -= i; } //Append a 0x00 octet to the padding string *(p++) = 0x00; //Copy the message to be encrypted memcpy(p, message, messageLength); //Rewind to the beginning of the encoded message p = ciphertext; //Debug message TRACE_DEBUG(" Encoded message\r\n"); TRACE_DEBUG_ARRAY(" ", p, k); //Start of exception handling block do { //Convert the encoded message EM to an integer message representative m error = mpiReadRaw(&m, p, k); //Conversion failed? if(error) break; //Apply the RSAEP encryption primitive error = rsaep(key, &m, &c); //Any error to report? if(error) break; //Convert the ciphertext representative c to a ciphertext of length k octets error = mpiWriteRaw(&c, ciphertext, k); //Conversion failed? if(error) break; //Length of the resulting ciphertext *ciphertextLength = k; //Debug message TRACE_DEBUG(" Ciphertext:\r\n"); TRACE_DEBUG_ARRAY(" ", ciphertext, *ciphertextLength); //End of exception handling block } while(0); //Free previously allocated memory mpiFree(&m); mpiFree(&c); //Return status code return error; }
error_t ecMult(const EcDomainParameters *params, EcPoint *r, const Mpi *d, const EcPoint *s) { error_t error; uint_t i; Mpi h; //Initialize multiple precision integer mpiInit(&h); //Check whether d == 0 if(!mpiCompInt(d, 0)) { //Set R = (1, 1, 0) MPI_CHECK(mpiSetValue(&r->x, 1)); MPI_CHECK(mpiSetValue(&r->y, 1)); MPI_CHECK(mpiSetValue(&r->z, 0)); } //Check whether d == 1 else if(!mpiCompInt(d, 1)) { //Set R = S MPI_CHECK(mpiCopy(&r->x, &s->x)); MPI_CHECK(mpiCopy(&r->y, &s->y)); MPI_CHECK(mpiCopy(&r->z, &s->z)); } //Check whether Sz == 0 else if(!mpiCompInt(&s->z, 0)) { //Set R = (1, 1, 0) MPI_CHECK(mpiSetValue(&r->x, 1)); MPI_CHECK(mpiSetValue(&r->y, 1)); MPI_CHECK(mpiSetValue(&r->z, 0)); } else { //Check whether Sz != 1 if(mpiCompInt(&s->z, 1)) { //Normalize S EC_CHECK(ecAffinify(params, r, s)); EC_CHECK(ecProjectify(params, r, r)); } else { //Set R = S MPI_CHECK(mpiCopy(&r->x, &s->x)); MPI_CHECK(mpiCopy(&r->y, &s->y)); MPI_CHECK(mpiCopy(&r->z, &s->z)); } //Left-to-right binary method #if 0 for(i = mpiGetBitLength(d) - 1; i >= 1; i--) { //Point doubling EC_CHECK(ecDouble(params, r, r)); if(mpiGetBitValue(d, i - 1)) { //Compute R = R + S EC_CHECK(ecFullAdd(params, r, r, s)); } } //Fast left-to-right binary method #else //Precompute h = 3 * d MPI_CHECK(mpiAdd(&h, d, d)); MPI_CHECK(mpiAdd(&h, &h, d)); //Scalar multiplication for(i = mpiGetBitLength(&h) - 2; i >= 1; i--) { //Point doubling EC_CHECK(ecDouble(params, r, r)); //Check whether h(i) == 1 and k(i) == 0 if(mpiGetBitValue(&h, i) && !mpiGetBitValue(d, i)) { //Compute R = R + S EC_CHECK(ecFullAdd(params, r, r, s)); } //Check whether h(i) == 0 and k(i) == 1 else if(!mpiGetBitValue(&h, i) && mpiGetBitValue(d, i)) { //Compute R = R - S EC_CHECK(ecFullSub(params, r, r, s)); } } #endif } end: //Release multiple precision integer mpiFree(&h); //Return status code return error; }
error_t ecAdd(const EcDomainParameters *params, EcPoint *r, const EcPoint *s, const EcPoint *t) { error_t error; Mpi t1; Mpi t2; Mpi t3; Mpi t4; Mpi t5; Mpi t6; Mpi t7; //Initialize multiple precision integers mpiInit(&t1); mpiInit(&t2); mpiInit(&t3); mpiInit(&t4); mpiInit(&t5); mpiInit(&t6); mpiInit(&t7); //Set t1 = Sx MPI_CHECK(mpiCopy(&t1, &s->x)); //Set t2 = Sy MPI_CHECK(mpiCopy(&t2, &s->y)); //Set t3 = Sz MPI_CHECK(mpiCopy(&t3, &s->z)); //Set t4 = Tx MPI_CHECK(mpiCopy(&t4, &t->x)); //Set t5 = Ty MPI_CHECK(mpiCopy(&t5, &t->y)); //Check whether Tz != 1 if(mpiCompInt(&t->z, 1)) { //Compute t6 = Tz MPI_CHECK(mpiCopy(&t6, &t->z)); //Compute t7 = t6^2 EC_CHECK(ecSqrMod(params, &t7, &t6)); //Compute t1 = t1 * t7 EC_CHECK(ecMulMod(params, &t1, &t1, &t7)); //Compute t7 = t6 * t7 EC_CHECK(ecMulMod(params, &t7, &t6, &t7)); //Compute t2 = t2 * t7 EC_CHECK(ecMulMod(params, &t2, &t2, &t7)); } //Compute t7 = t3^2 EC_CHECK(ecSqrMod(params, &t7, &t3)); //Compute t4 = t4 * t7 EC_CHECK(ecMulMod(params, &t4, &t4, &t7)); //Compute t7 = t3 * t7 EC_CHECK(ecMulMod(params, &t7, &t3, &t7)); //Compute t5 = t5 * t7 EC_CHECK(ecMulMod(params, &t5, &t5, &t7)); //Compute t4 = t1 - t4 EC_CHECK(ecSubMod(params, &t4, &t1, &t4)); //Compute t5 = t2 - t5 EC_CHECK(ecSubMod(params, &t5, &t2, &t5)); //Check whether t4 == 0 if(!mpiCompInt(&t4, 0)) { //Check whether t5 == 0 if(!mpiCompInt(&t5, 0)) { //Set R = (0, 0, 0) MPI_CHECK(mpiSetValue(&r->x, 0)); MPI_CHECK(mpiSetValue(&r->y, 0)); MPI_CHECK(mpiSetValue(&r->z, 0)); } else { //Set R = (1, 1, 0) MPI_CHECK(mpiSetValue(&r->x, 1)); MPI_CHECK(mpiSetValue(&r->y, 1)); MPI_CHECK(mpiSetValue(&r->z, 0)); } } else { //Compute t1 = 2 * t1 - t4 EC_CHECK(ecAddMod(params, &t1, &t1, &t1)); EC_CHECK(ecSubMod(params, &t1, &t1, &t4)); //Compute t2 = 2 * t2 - t5 EC_CHECK(ecAddMod(params, &t2, &t2, &t2)); EC_CHECK(ecSubMod(params, &t2, &t2, &t5)); //Check whether Tz != 1 if(mpiCompInt(&t->z, 1)) { //Compute t3 = t3 * t6 EC_CHECK(ecMulMod(params, &t3, &t3, &t6)); } //Compute t3 = t3 * t4 EC_CHECK(ecMulMod(params, &t3, &t3, &t4)); //Compute t7 = t4^2 EC_CHECK(ecSqrMod(params, &t7, &t4)); //Compute t4 = t4 * t7 EC_CHECK(ecMulMod(params, &t4, &t4, &t7)); //Compute t7 = t1 * t7 EC_CHECK(ecMulMod(params, &t7, &t1, &t7)); //Compute t1 = t5^2 EC_CHECK(ecSqrMod(params, &t1, &t5)); //Compute t1 = t1 - t7 EC_CHECK(ecSubMod(params, &t1, &t1, &t7)); //Compute t7 = t7 - 2 * t1 EC_CHECK(ecAddMod(params, &t6, &t1, &t1)); EC_CHECK(ecSubMod(params, &t7, &t7, &t6)); //Compute t5 = t5 * t7 EC_CHECK(ecMulMod(params, &t5, &t5, &t7)); //Compute t4 = t2 * t4 EC_CHECK(ecMulMod(params, &t4, &t2, &t4)); //Compute t2 = t5 - t4 EC_CHECK(ecSubMod(params, &t2, &t5, &t4)); //Compute t2 = t2 / 2 if(mpiIsEven(&t2)) { MPI_CHECK(mpiShiftRight(&t2, 1)); } else { MPI_CHECK(mpiAdd(&t2, &t2, ¶ms->p)); MPI_CHECK(mpiShiftRight(&t2, 1)); } //Set Rx = t1 MPI_CHECK(mpiCopy(&r->x, &t1)); //Set Ry = t2 MPI_CHECK(mpiCopy(&r->y, &t2)); //Set Rz = t3 MPI_CHECK(mpiCopy(&r->z, &t3)); } end: //Release multiple precision integers mpiFree(&t1); mpiFree(&t2); mpiFree(&t3); mpiFree(&t4); mpiFree(&t5); mpiFree(&t6); mpiFree(&t7); //Return status code return error; }
error_t ecDouble(const EcDomainParameters *params, EcPoint *r, const EcPoint *s) { error_t error; Mpi t1; Mpi t2; Mpi t3; Mpi t4; Mpi t5; //Initialize multiple precision integers mpiInit(&t1); mpiInit(&t2); mpiInit(&t3); mpiInit(&t4); mpiInit(&t5); //Set t1 = Sx MPI_CHECK(mpiCopy(&t1, &s->x)); //Set t2 = Sy MPI_CHECK(mpiCopy(&t2, &s->y)); //Set t3 = Sz MPI_CHECK(mpiCopy(&t3, &s->z)); //Point at the infinity? if(!mpiCompInt(&t3, 0)) { //Set R = (1, 1, 0) MPI_CHECK(mpiSetValue(&r->x, 1)); MPI_CHECK(mpiSetValue(&r->y, 1)); MPI_CHECK(mpiSetValue(&r->z, 0)); } else { //SECP K1 elliptic curve? if(params->type == EC_CURVE_TYPE_SECP_K1) { //Compute t5 = t1^2 EC_CHECK(ecSqrMod(params, &t5, &t1)); //Compute t4 = 3 * t5 EC_CHECK(ecAddMod(params, &t4, &t5, &t5)); EC_CHECK(ecAddMod(params, &t4, &t4, &t5)); } //SECP R1 elliptic curve? else if(params->type == EC_CURVE_TYPE_SECP_R1) { //Compute t4 = t3^2 EC_CHECK(ecSqrMod(params, &t4, &t3)); //Compute t5 = t1 - t4 EC_CHECK(ecSubMod(params, &t5, &t1, &t4)); //Compute t4 = t1 + t4 EC_CHECK(ecAddMod(params, &t4, &t1, &t4)); //Compute t5 = t4 * t5 EC_CHECK(ecMulMod(params, &t5, &t4, &t5)); //Compute t4 = 3 * t5 EC_CHECK(ecAddMod(params, &t4, &t5, &t5)); EC_CHECK(ecAddMod(params, &t4, &t4, &t5)); } else { //Compute t4 = t3^4 EC_CHECK(ecSqrMod(params, &t4, &t3)); EC_CHECK(ecSqrMod(params, &t4, &t4)); //Compute t4 = a * t4 EC_CHECK(ecMulMod(params, &t4, &t4, ¶ms->a)); //Compute t5 = t1^2 EC_CHECK(ecSqrMod(params, &t5, &t1)); //Compute t4 = t4 + 3 * t5 EC_CHECK(ecAddMod(params, &t4, &t4, &t5)); EC_CHECK(ecAddMod(params, &t4, &t4, &t5)); EC_CHECK(ecAddMod(params, &t4, &t4, &t5)); } //Compute t3 = t3 * t2 EC_CHECK(ecMulMod(params, &t3, &t3, &t2)); //Compute t3 = 2 * t3 EC_CHECK(ecAddMod(params, &t3, &t3, &t3)); //Compute t2 = t2^2 EC_CHECK(ecSqrMod(params, &t2, &t2)); //Compute t5 = t1 * t2 EC_CHECK(ecMulMod(params, &t5, &t1, &t2)); //Compute t5 = 4 * t5 EC_CHECK(ecAddMod(params, &t5, &t5, &t5)); EC_CHECK(ecAddMod(params, &t5, &t5, &t5)); //Compute t1 = t4^2 EC_CHECK(ecSqrMod(params, &t1, &t4)); //Compute t1 = t1 - 2 * t5 EC_CHECK(ecSubMod(params, &t1, &t1, &t5)); EC_CHECK(ecSubMod(params, &t1, &t1, &t5)); //Compute t2 = t2^2 EC_CHECK(ecSqrMod(params, &t2, &t2)); //Compute t2 = 8 * t2 EC_CHECK(ecAddMod(params, &t2, &t2, &t2)); EC_CHECK(ecAddMod(params, &t2, &t2, &t2)); EC_CHECK(ecAddMod(params, &t2, &t2, &t2)); //Compute t5 = t5 - t1 EC_CHECK(ecSubMod(params, &t5, &t5, &t1)); //Compute t5 = t4 * t5 EC_CHECK(ecMulMod(params, &t5, &t4, &t5)); //Compute t2 = t5 - t2 EC_CHECK(ecSubMod(params, &t2, &t5, &t2)); //Set Rx = t1 MPI_CHECK(mpiCopy(&r->x, &t1)); //Set Ry = t2 MPI_CHECK(mpiCopy(&r->y, &t2)); //Set Rz = t3 MPI_CHECK(mpiCopy(&r->z, &t3)); } end: //Release multiple precision integers mpiFree(&t1); mpiFree(&t2); mpiFree(&t3); mpiFree(&t4); mpiFree(&t5); //Return status code return error; }