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 ecSubMod(const EcDomainParameters *params, Mpi *r, const Mpi *a, const Mpi *b) { error_t error; //Compute R = A - B MPI_CHECK(mpiSub(r, a, b)); //Compute R = (A - B) mod p if(mpiCompInt(r, 0) < 0) { MPI_CHECK(mpiAdd(r, r, ¶ms->p)); } end: //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; }