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 rsaep(const RsaPublicKey *key, const Mpi *m, Mpi *c) { //Ensure the RSA public key is valid if(!key->n.size || !key->e.size) return ERROR_INVALID_PARAMETER; //The message representative m shall be between 0 and n - 1 if(mpiCompInt(m, 0) < 0 || mpiComp(m, &key->n) >= 0) return ERROR_OUT_OF_RANGE; //Perform modular exponentiation (c = m ^ e mod n) return mpiExpMod(c, m, &key->e, &key->n); }
error_t dhGenerateKeyPair(DhContext *context, const PrngAlgo *prngAlgo, void *prngContext) { error_t error; uint_t k; //Debug message TRACE_DEBUG("Generating Diffie-Hellman key pair...\r\n"); //Get the length in bits of the prime p k = mpiGetBitLength(&context->params.p); //Ensure the length is valid if(!k) return ERROR_INVALID_PARAMETER; //The private value shall be randomly generated error = mpiRand(&context->xa, k, prngAlgo, prngContext); //Any error to report? if(error) return error; //The private value shall be less than p if(mpiComp(&context->xa, &context->params.p) >= 0) { //Shift value to the right error = mpiShiftRight(&context->xa, 1); //Any error to report? if(error) return error; } //Debug message TRACE_DEBUG(" Private value:\r\n"); TRACE_DEBUG_MPI(" ", &context->xa); //Calculate the corresponding public value (ya = g ^ xa mod p) error = mpiExpMod(&context->ya, &context->params.g, &context->xa, &context->params.p); //Any error to report? if(error) return error; //Debug message TRACE_DEBUG(" Public value:\r\n"); TRACE_DEBUG_MPI(" ", &context->ya); //Check public value error = dhCheckPublicKey(&context->params, &context->ya); //Weak public value? if(error) return error; //Public value successfully generated return NO_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; }