const bool FrostIdentity::FromPublicKey(const std::string &publickey) { std::vector<std::string> keyparts; std::vector<unsigned char> edata; std::vector<unsigned char> ndata; mbedtls_rsa_free(&m_rsa); mbedtls_rsa_init(&m_rsa,MBEDTLS_RSA_PKCS_V21,MBEDTLS_MD_SHA1); StringFunctions::Split(publickey,":",keyparts); if(keyparts.size()==2) { Base64::Decode(keyparts[0],edata); Base64::Decode(keyparts[1],ndata); mbedtls_mpi_init(&m_rsa.N); mbedtls_mpi_init(&m_rsa.E); mbedtls_mpi_read_binary(&m_rsa.N,&ndata[0],ndata.size()); mbedtls_mpi_read_binary(&m_rsa.E,&edata[0],edata.size()); m_publickey=publickey; return true; } else { return false; } }
/* * Compute and write signature */ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; mbedtls_mpi r, s; mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s ); #if defined(MBEDTLS_ECDSA_DETERMINISTIC) (void) f_rng; (void) p_rng; MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d, hash, hlen, md_alg ) ); #else (void) md_alg; MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, hash, hlen, f_rng, p_rng ) ); #endif MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); cleanup: mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s ); return( ret ); }
/* * Init verify sign sub-context */ static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx ) { ctx->sign_tries = 0; ctx->key_tries = 0; mbedtls_mpi_init( &ctx->k ); mbedtls_mpi_init( &ctx->r ); ctx->state = ecdsa_sig_init; }
/* * Restartable read and check signature */ int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen, mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret; unsigned char *p = (unsigned char *) sig; const unsigned char *end = sig + slen; size_t len; mbedtls_mpi r, s; mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s ); if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } if( p + len != end ) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; goto cleanup; } if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) { ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } #if defined(MBEDTLS_ECDSA_VERIFY_ALT) if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, &ctx->Q, &r, &s ) ) != 0 ) goto cleanup; #else if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen, &ctx->Q, &r, &s, rs_ctx ) ) != 0 ) goto cleanup; #endif /* MBEDTLS_ECDSA_VERIFY_ALT */ /* At this point we know that the buffer starts with a valid signature. * Return 0 if the buffer just contains the signature, and a specific * error code if the valid signature is followed by more data. */ if( p != end ) ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; cleanup: mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s ); return( ret ); }
bool ECDSA_Verify(COSE * pSigner, int index, const cn_cbor * pKey, int cbitDigest, const byte * rgbToSign, size_t cbToSign, cose_errback * perr) { mbedtls_ecp_keypair keypair; mbedtls_mpi r; mbedtls_mpi s; mbedtls_md_type_t mdType; const mbedtls_md_info_t *pmdInfo; byte rgbDigest[MBEDTLS_MD_MAX_SIZE]; cn_cbor * pSig; bool result = false; mbedtls_ecp_keypair_init(&keypair); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); if(!ECKey_From(pKey, &keypair, perr)) goto errorReturn; switch(cbitDigest) { case 256: mdType = MBEDTLS_MD_SHA256; break; case 384: mdType = MBEDTLS_MD_SHA384; break; case 512: mdType = MBEDTLS_MD_SHA512; break; default: FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER); } pmdInfo = mbedtls_md_info_from_type(mdType); CHECK_CONDITION(pmdInfo != NULL, COSE_ERR_INVALID_PARAMETER); CHECK_CONDITION(mbedtls_md(pmdInfo, rgbToSign, cbToSign, rgbDigest) == 0, COSE_ERR_INVALID_PARAMETER); pSig = _COSE_arrayget_int(pSigner, index); CHECK_CONDITION((pSig != NULL) && (pSig->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER); CHECK_CONDITION(mbedtls_mpi_read_binary( &r, pSig->v.bytes, pSig->length / 2 ) == 0, COSE_ERR_OUT_OF_MEMORY); CHECK_CONDITION(mbedtls_mpi_read_binary( &s, pSig->v.bytes + pSig->length / 2, pSig->length / 2 ) == 0, COSE_ERR_OUT_OF_MEMORY); CHECK_CONDITION(mbedtls_ecdsa_verify(&keypair.grp, rgbDigest, mbedtls_md_get_size(pmdInfo), &keypair.Q, &r, &s) == 0, COSE_ERR_CRYPTO_FAIL); result = true; errorReturn: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); mbedtls_ecp_keypair_free(&keypair); return result; }
void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ) { memset( ctx, 0, sizeof(mbedtls_x509write_cert) ); mbedtls_mpi_init( &ctx->serial ); ctx->version = MBEDTLS_X509_CRT_VERSION_3; }
/* Z = (X * Y) mod M Not an mbedTLS function */ int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M) { int ret; size_t num_words = hardware_words_needed(M); mbedtls_mpi Rinv; mbedtls_mpi_uint Mprime; /* Calculate and load the first stage montgomery multiplication */ mbedtls_mpi_init(&Rinv); MBEDTLS_MPI_CHK(calculate_rinv(&Rinv, M, num_words)); Mprime = modular_inverse(M); esp_mpi_acquire_hardware(); /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */ mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, num_words); mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words); mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, &Rinv, num_words); REG_WRITE(RSA_M_DASH_REG, (uint32_t)Mprime); /* "mode" register loaded with number of 512-bit blocks, minus 1 */ REG_WRITE(RSA_MULT_MODE_REG, (num_words / 16) - 1); /* Execute first stage montgomery multiplication */ execute_op(RSA_MULT_START_REG); /* execute second stage */ MBEDTLS_MPI_CHK( modular_multiply_finish(Z, X, Y, num_words) ); esp_mpi_release_hardware(); cleanup: mbedtls_mpi_free(&Rinv); return ret; }
/* * Deterministic signature wrapper */ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, mbedtls_md_type_t md_alg ) { int ret; mbedtls_hmac_drbg_context rng_ctx; unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; size_t grp_len = ( grp->nbits + 7 ) / 8; const mbedtls_md_info_t *md_info; mbedtls_mpi h; if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); mbedtls_mpi_init( &h ); mbedtls_hmac_drbg_init( &rng_ctx ); /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len ); ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, mbedtls_hmac_drbg_random, &rng_ctx ); cleanup: mbedtls_hmac_drbg_free( &rng_ctx ); mbedtls_mpi_free( &h ); return( ret ); }
result_t X509Cert::get_serial(exlib::string &retVal) { mbedtls_x509_crt *crt = get_crt(); if (!crt) return CHECK_ERROR(CALL_E_INVALID_CALL); int32_t ret; mbedtls_mpi serial; mbedtls_mpi_init(&serial); ret = mbedtls_mpi_read_binary(&serial, crt->serial.p, crt->serial.len); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); retVal.resize(8192); size_t sz = retVal.length(); ret = mbedtls_mpi_write_string(&serial, 10, &retVal[0], sz, &sz); mbedtls_mpi_free(&serial); if (ret != 0) return CHECK_ERROR(_ssl::setError(ret)); retVal.resize(sz - 1); return 0; }
/* * Read and check signature */ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen ) { int ret; unsigned char *p = (unsigned char *) sig; const unsigned char *end = sig + slen; size_t len; mbedtls_mpi r, s; mbedtls_mpi_init( &r ); mbedtls_mpi_init( &s ); if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } if( p + len != end ) { ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; goto cleanup; } if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) { ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, &ctx->Q, &r, &s ) ) != 0 ) goto cleanup; if( p != end ) ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; cleanup: mbedtls_mpi_free( &r ); mbedtls_mpi_free( &s ); return( ret ); }
bignum ssh_mbedcry_bn_new(void) { bignum bn; bn = malloc(sizeof(mbedtls_mpi)); if (bn) { mbedtls_mpi_init(bn); } return bn; }
/* * Verify sanity of parameter with regards to P * * Parameter should be: 2 <= public_param <= P - 2 * * For more information on the attack, see: * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 */ static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P ) { mbedtls_mpi L, U; int ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) ); if( mbedtls_mpi_cmp_mpi( param, &L ) >= 0 && mbedtls_mpi_cmp_mpi( param, &U ) <= 0 ) { ret = 0; } cleanup: mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U ); return( ret ); }
/* Calculate Rinv = RR^2 mod M, where: * * R = b^n where b = 2^32, n=num_words, * R = 2^N (where N=num_bits) * RR = R^2 = 2^(2*N) (where N=num_bits=num_words*32) * * This calculation is computationally expensive (mbedtls_mpi_mod_mpi) * so caller should cache the result where possible. * * DO NOT call this function while holding esp_mpi_acquire_hardware(). * */ static int calculate_rinv(mbedtls_mpi *Rinv, const mbedtls_mpi *M, int num_words) { int ret; size_t num_bits = num_words * 32; mbedtls_mpi RR; mbedtls_mpi_init(&RR); MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&RR, num_bits * 2, 1)); MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(Rinv, &RR, M)); cleanup: mbedtls_mpi_free(&RR); return ret; }
TEE_Result crypto_acipher_ecc_shared_secret(struct ecc_keypair *private_key, struct ecc_public_key *public_key, void *secret, unsigned long *secret_len) { TEE_Result res = TEE_SUCCESS; int lmd_res = 0; uint8_t one[1] = { 1 }; mbedtls_ecdh_context ecdh; size_t out_len = 0; memset(&ecdh, 0, sizeof(ecdh)); mbedtls_ecdh_init(&ecdh); lmd_res = mbedtls_ecp_group_load(&ecdh.grp, private_key->curve); if (lmd_res != 0) { res = TEE_ERROR_NOT_SUPPORTED; goto out; } ecdh.d = *(mbedtls_mpi *)private_key->d; ecdh.Qp.X = *(mbedtls_mpi *)public_key->x; ecdh.Qp.Y = *(mbedtls_mpi *)public_key->y; mbedtls_mpi_read_binary(&ecdh.Qp.Z, one, sizeof(one)); lmd_res = mbedtls_ecdh_calc_secret(&ecdh, &out_len, secret, *secret_len, mbd_rand, NULL); if (lmd_res != 0) { res = get_tee_result(lmd_res); goto out; } *secret_len = out_len; out: /* Reset mpi to skip freeing here, those mpis will be freed with key */ mbedtls_mpi_init(&ecdh.d); mbedtls_mpi_init(&ecdh.Qp.X); mbedtls_mpi_init(&ecdh.Qp.Y); mbedtls_ecdh_free(&ecdh); return res; }
/* * Derive and export the shared secret (G^Y)^X mod P */ int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, unsigned char *output, size_t output_size, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; mbedtls_mpi GYb; if( ctx == NULL || output_size < ctx->len ) return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) return( ret ); mbedtls_mpi_init( &GYb ); /* Blind peer's value */ if( f_rng != NULL ) { MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); } else MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) ); /* Do modular exponentiation */ MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X, &ctx->P, &ctx->RP ) ); /* Unblind secret value */ if( f_rng != NULL ) { MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); } *olen = mbedtls_mpi_size( &ctx->K ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) ); cleanup: mbedtls_mpi_free( &GYb ); if( ret != 0 ) return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret ); return( 0 ); }
/* Deal with the case when X & Y are too long for the hardware unit, by splitting one operand into two halves. Y must be the longer operand Slice Y into Yp, Ypp such that: Yp = lower 'b' bits of Y Ypp = upper 'b' bits of Y (right shifted) Such that Z = X * Y Z = X * (Yp + Ypp<<b) Z = (X * Yp) + (X * Ypp<<b) Note that this function may recurse multiple times, if both X & Y are too long for the hardware multiplication unit. */ static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t bits_y, size_t words_result) { int ret; mbedtls_mpi Ztemp; const size_t limbs_y = (bits_y + biL - 1) / biL; /* Rather than slicing in two on bits we slice on limbs (32 bit words) */ const size_t limbs_slice = limbs_y / 2; /* Yp holds lower bits of Y (declared to reuse Y's array contents to save on copying) */ const mbedtls_mpi Yp = { .p = Y->p, .n = limbs_slice, .s = Y->s }; /* Ypp holds upper bits of Y, right shifted (also reuses Y's array contents) */ const mbedtls_mpi Ypp = { .p = Y->p + limbs_slice, .n = limbs_y - limbs_slice, .s = Y->s }; mbedtls_mpi_init(&Ztemp); /* Grow Z to result size early, avoid interim allocations */ mbedtls_mpi_grow(Z, words_result); /* Get result Ztemp = Yp * X (need temporary variable Ztemp) */ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi(&Ztemp, X, &Yp) ); /* Z = Ypp * Y */ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi(Z, X, &Ypp) ); /* Z = Z << b */ MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(Z, limbs_slice * biL) ); /* Z += Ztemp */ MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi(Z, Z, &Ztemp) ); cleanup: mbedtls_mpi_free(&Ztemp); return ret; }
/* * Do an RSA public key operation */ int mbedtls_rsa_public( mbedtls_rsa_context *ctx, const unsigned char *input, unsigned char *output ) { int ret; size_t olen; mbedtls_mpi T; mbedtls_mpi_init( &T ); #if defined(MBEDTLS_THREADING_C) if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) return( ret ); #endif MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) { ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; goto cleanup; } olen = ctx->len; MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); cleanup: #if defined(MBEDTLS_THREADING_C) if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); #endif mbedtls_mpi_free( &T ); if( ret != 0 ) return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret ); return( 0 ); }
/* * Verify ECDSA signature of hashed message (SEC1 4.1.4) * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) */ static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, const unsigned char *buf, size_t blen, const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s, mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret; mbedtls_mpi e, s_inv, u1, u2; mbedtls_ecp_point R; mbedtls_mpi *pu1 = &u1, *pu2 = &u2; mbedtls_ecp_point_init( &R ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ if( grp->N.p == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); ECDSA_RS_ENTER( ver ); #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->ver != NULL ) { /* redirect to our context */ pu1 = &rs_ctx->ver->u1; pu2 = &rs_ctx->ver->u2; /* jump to current step */ if( rs_ctx->ver->state == ecdsa_ver_muladd ) goto muladd; } #endif /* MBEDTLS_ECP_RESTARTABLE */ /* * Step 1: make sure r and s are in range 1..n-1 */ if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 || mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 ) { ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; goto cleanup; } /* * Step 3: derive MPI from hashed message */ MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); /* * Step 4: u1 = e / s mod n, u2 = r / s mod n */ ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 ); MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) ); #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->ver != NULL ) rs_ctx->ver->state = ecdsa_ver_muladd; muladd: #endif /* * Step 5: R = u1 G + u2 Q */ MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp, &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) ); if( mbedtls_ecp_is_zero( &R ) ) { ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; goto cleanup; } /* * Step 6: convert xR to an integer (no-op) * Step 7: reduce xR mod n (gives v) */ MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) ); /* * Step 8: check if v (that is, R.X) is equal to r */ if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 ) { ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; goto cleanup; } cleanup: mbedtls_ecp_point_free( &R ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); ECDSA_RS_LEAVE( ver ); return( ret ); }
/* * Do an RSA private key operation */ int mbedtls_rsa_private( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, const unsigned char *input, unsigned char *output ) { int ret; size_t olen; mbedtls_mpi T, T1, T2; /* Make sure we have private key info, prevent possible misuse */ if( ctx->P.p == NULL || ctx->Q.p == NULL || ctx->D.p == NULL ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); #if defined(MBEDTLS_THREADING_C) if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) return( ret ); #endif MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) { ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; goto cleanup; } if( f_rng != NULL ) { /* * Blinding * T = T * Vi mod N */ MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); } #if defined(MBEDTLS_RSA_NO_CRT) MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); #else /* * faster decryption using the CRT * * T1 = input ^ dP mod P * T2 = input ^ dQ mod Q */ MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); /* * T = (T1 - T2) * (Q^-1 mod P) mod P */ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T1, &T2 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->QP ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T1, &ctx->P ) ); /* * T = T2 + T * Q */ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->Q ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &T2, &T1 ) ); #endif /* MBEDTLS_RSA_NO_CRT */ if( f_rng != NULL ) { /* * Unblind * T = T * Vf mod N */ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); } olen = ctx->len; MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); cleanup: #if defined(MBEDTLS_THREADING_C) if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); #endif mbedtls_mpi_free( &T ); mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); if( ret != 0 ) return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); return( 0 ); }
TEE_Result crypto_acipher_ecc_verify(uint32_t algo, struct ecc_public_key *key, const uint8_t *msg, size_t msg_len, const uint8_t *sig, size_t sig_len) { TEE_Result res = TEE_SUCCESS; int lmd_res = 0; mbedtls_ecdsa_context ecdsa; size_t key_size_bytes, key_size_bits = 0; uint8_t one[1] = { 1 }; mbedtls_mpi r; mbedtls_mpi s; memset(&ecdsa, 0, sizeof(ecdsa)); memset(&r, 0, sizeof(r)); memset(&s, 0, sizeof(s)); if (algo == 0) return TEE_ERROR_BAD_PARAMETERS; mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); mbedtls_ecdsa_init(&ecdsa); lmd_res = mbedtls_ecp_group_load(&ecdsa.grp, key->curve); if (lmd_res != 0) { res = TEE_ERROR_NOT_SUPPORTED; goto out; } ecdsa.Q.X = *(mbedtls_mpi *)key->x; ecdsa.Q.Y = *(mbedtls_mpi *)key->y; mbedtls_mpi_read_binary(&ecdsa.Q.Z, one, sizeof(one)); res = ecc_get_keysize(key->curve, algo, &key_size_bytes, &key_size_bits); if (res != TEE_SUCCESS) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } /* check keysize vs sig_len */ if ((key_size_bytes * 2) != sig_len) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } mbedtls_mpi_read_binary(&r, sig, sig_len / 2); mbedtls_mpi_read_binary(&s, sig + sig_len / 2, sig_len / 2); lmd_res = mbedtls_ecdsa_verify(&ecdsa.grp, msg, msg_len, &ecdsa.Q, &r, &s); if (lmd_res != 0) { FMSG("mbedtls_ecdsa_verify failed, returned 0x%x", -lmd_res); res = get_tee_result(lmd_res); } out: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); /* Reset mpi to skip freeing here, those mpis will be freed with key */ mbedtls_mpi_init(&ecdsa.Q.X); mbedtls_mpi_init(&ecdsa.Q.Y); mbedtls_ecdsa_free(&ecdsa); return res; }
TEE_Result crypto_acipher_ecc_sign(uint32_t algo, struct ecc_keypair *key, const uint8_t *msg, size_t msg_len, uint8_t *sig, size_t *sig_len) { TEE_Result res = TEE_SUCCESS; int lmd_res = 0; const mbedtls_pk_info_t *pk_info = NULL; mbedtls_ecdsa_context ecdsa; size_t key_size_bytes = 0; size_t key_size_bits = 0; mbedtls_mpi r; mbedtls_mpi s; memset(&ecdsa, 0, sizeof(ecdsa)); memset(&r, 0, sizeof(r)); memset(&s, 0, sizeof(s)); if (algo == 0) return TEE_ERROR_BAD_PARAMETERS; mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); mbedtls_ecdsa_init(&ecdsa); lmd_res = mbedtls_ecp_group_load(&ecdsa.grp, key->curve); if (lmd_res != 0) { res = TEE_ERROR_NOT_SUPPORTED; goto out; } ecdsa.d = *(mbedtls_mpi *)key->d; res = ecc_get_keysize(key->curve, algo, &key_size_bytes, &key_size_bits); if (res != TEE_SUCCESS) goto out; pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECDSA); if (pk_info == NULL) { res = TEE_ERROR_NOT_SUPPORTED; goto out; } lmd_res = mbedtls_ecdsa_sign(&ecdsa.grp, &r, &s, &ecdsa.d, msg, msg_len, mbd_rand, NULL); if (lmd_res == 0) { *sig_len = 2 * key_size_bytes; memset(sig, 0, *sig_len); mbedtls_mpi_write_binary(&r, sig + *sig_len / 2 - mbedtls_mpi_size(&r), mbedtls_mpi_size(&r)); mbedtls_mpi_write_binary(&s, sig + *sig_len - mbedtls_mpi_size(&s), mbedtls_mpi_size(&s)); res = TEE_SUCCESS; } else { FMSG("mbedtls_ecdsa_sign failed, returned 0x%x\n", -lmd_res); res = TEE_ERROR_GENERIC; } out: mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); /* Reset mpi to skip freeing here, those mpis will be freed with key */ mbedtls_mpi_init(&ecdsa.d); mbedtls_ecdsa_free(&ecdsa); return res; }
int main( int argc, char *argv[] ) { int ret = 0; mbedtls_x509_crt issuer_crt; mbedtls_pk_context loaded_issuer_key, loaded_subject_key; mbedtls_pk_context *issuer_key = &loaded_issuer_key, *subject_key = &loaded_subject_key; char buf[1024]; char issuer_name[128]; int i; char *p, *q, *r; #if defined(MBEDTLS_X509_CSR_PARSE_C) char subject_name[128]; mbedtls_x509_csr csr; #endif mbedtls_x509write_cert crt; mbedtls_mpi serial; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; const char *pers = "crt example app"; /* * Set to sane values */ mbedtls_x509write_crt_init( &crt ); mbedtls_x509write_crt_set_md_alg( &crt, MBEDTLS_MD_SHA256 ); mbedtls_pk_init( &loaded_issuer_key ); mbedtls_pk_init( &loaded_subject_key ); mbedtls_mpi_init( &serial ); mbedtls_ctr_drbg_init( &ctr_drbg ); #if defined(MBEDTLS_X509_CSR_PARSE_C) mbedtls_x509_csr_init( &csr ); #endif mbedtls_x509_crt_init( &issuer_crt ); memset( buf, 0, 1024 ); if( argc == 0 ) { usage: mbedtls_printf( USAGE ); ret = 1; goto exit; } opt.issuer_crt = DFL_ISSUER_CRT; opt.request_file = DFL_REQUEST_FILE; opt.subject_key = DFL_SUBJECT_KEY; opt.issuer_key = DFL_ISSUER_KEY; opt.subject_pwd = DFL_SUBJECT_PWD; opt.issuer_pwd = DFL_ISSUER_PWD; opt.output_file = DFL_OUTPUT_FILENAME; opt.subject_name = DFL_SUBJECT_NAME; opt.issuer_name = DFL_ISSUER_NAME; opt.not_before = DFL_NOT_BEFORE; opt.not_after = DFL_NOT_AFTER; opt.serial = DFL_SERIAL; opt.selfsign = DFL_SELFSIGN; opt.is_ca = DFL_IS_CA; opt.max_pathlen = DFL_MAX_PATHLEN; opt.key_usage = DFL_KEY_USAGE; opt.ns_cert_type = DFL_NS_CERT_TYPE; for( i = 1; i < argc; i++ ) { p = argv[i]; if( ( q = strchr( p, '=' ) ) == NULL ) goto usage; *q++ = '\0'; if( strcmp( p, "request_file" ) == 0 ) opt.request_file = q; else if( strcmp( p, "subject_key" ) == 0 ) opt.subject_key = q; else if( strcmp( p, "issuer_key" ) == 0 ) opt.issuer_key = q; else if( strcmp( p, "subject_pwd" ) == 0 ) opt.subject_pwd = q; else if( strcmp( p, "issuer_pwd" ) == 0 ) opt.issuer_pwd = q; else if( strcmp( p, "issuer_crt" ) == 0 ) opt.issuer_crt = q; else if( strcmp( p, "output_file" ) == 0 ) opt.output_file = q; else if( strcmp( p, "subject_name" ) == 0 ) { opt.subject_name = q; } else if( strcmp( p, "issuer_name" ) == 0 ) { opt.issuer_name = q; } else if( strcmp( p, "not_before" ) == 0 ) { opt.not_before = q; } else if( strcmp( p, "not_after" ) == 0 ) { opt.not_after = q; } else if( strcmp( p, "serial" ) == 0 ) { opt.serial = q; } else if( strcmp( p, "selfsign" ) == 0 ) { opt.selfsign = atoi( q ); if( opt.selfsign < 0 || opt.selfsign > 1 ) goto usage; } else if( strcmp( p, "is_ca" ) == 0 ) { opt.is_ca = atoi( q ); if( opt.is_ca < 0 || opt.is_ca > 1 ) goto usage; } else if( strcmp( p, "max_pathlen" ) == 0 ) { opt.max_pathlen = atoi( q ); if( opt.max_pathlen < -1 || opt.max_pathlen > 127 ) goto usage; } else if( strcmp( p, "key_usage" ) == 0 ) { while( q != NULL ) { if( ( r = strchr( q, ',' ) ) != NULL ) *r++ = '\0'; if( strcmp( q, "digital_signature" ) == 0 ) opt.key_usage |= MBEDTLS_X509_KU_DIGITAL_SIGNATURE; else if( strcmp( q, "non_repudiation" ) == 0 ) opt.key_usage |= MBEDTLS_X509_KU_NON_REPUDIATION; else if( strcmp( q, "key_encipherment" ) == 0 ) opt.key_usage |= MBEDTLS_X509_KU_KEY_ENCIPHERMENT; else if( strcmp( q, "data_encipherment" ) == 0 ) opt.key_usage |= MBEDTLS_X509_KU_DATA_ENCIPHERMENT; else if( strcmp( q, "key_agreement" ) == 0 ) opt.key_usage |= MBEDTLS_X509_KU_KEY_AGREEMENT; else if( strcmp( q, "key_cert_sign" ) == 0 ) opt.key_usage |= MBEDTLS_X509_KU_KEY_CERT_SIGN; else if( strcmp( q, "crl_sign" ) == 0 ) opt.key_usage |= MBEDTLS_X509_KU_CRL_SIGN; else goto usage; q = r; } } else if( strcmp( p, "ns_cert_type" ) == 0 ) { while( q != NULL ) { if( ( r = strchr( q, ',' ) ) != NULL ) *r++ = '\0'; if( strcmp( q, "ssl_client" ) == 0 ) opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT; else if( strcmp( q, "ssl_server" ) == 0 ) opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER; else if( strcmp( q, "email" ) == 0 ) opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL; else if( strcmp( q, "object_signing" ) == 0 ) opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING; else if( strcmp( q, "ssl_ca" ) == 0 ) opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CA; else if( strcmp( q, "email_ca" ) == 0 ) opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA; else if( strcmp( q, "object_signing_ca" ) == 0 ) opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA; else goto usage; q = r; } } else goto usage; } mbedtls_printf("\n"); /* * 0. Seed the PRNG */ mbedtls_printf( " . Seeding the random number generator..." ); fflush( stdout ); mbedtls_entropy_init( &entropy ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d - %s\n", ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); // Parse serial to MPI // mbedtls_printf( " . Reading serial number..." ); fflush( stdout ); if( ( ret = mbedtls_mpi_read_string( &serial, 10, opt.serial ) ) != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_mpi_read_string returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); // Parse issuer certificate if present // if( !opt.selfsign && strlen( opt.issuer_crt ) ) { /* * 1.0.a. Load the certificates */ mbedtls_printf( " . Loading the issuer certificate ..." ); fflush( stdout ); if( ( ret = mbedtls_x509_crt_parse_file( &issuer_crt, opt.issuer_crt ) ) != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } ret = mbedtls_x509_dn_gets( issuer_name, sizeof(issuer_name), &issuer_crt.subject ); if( ret < 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509_dn_gets returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } opt.issuer_name = issuer_name; mbedtls_printf( " ok\n" ); } #if defined(MBEDTLS_X509_CSR_PARSE_C) // Parse certificate request if present // if( !opt.selfsign && strlen( opt.request_file ) ) { /* * 1.0.b. Load the CSR */ mbedtls_printf( " . Loading the certificate request ..." ); fflush( stdout ); if( ( ret = mbedtls_x509_csr_parse_file( &csr, opt.request_file ) ) != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509_csr_parse_file returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } ret = mbedtls_x509_dn_gets( subject_name, sizeof(subject_name), &csr.subject ); if( ret < 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509_dn_gets returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } opt.subject_name = subject_name; subject_key = &csr.pk; mbedtls_printf( " ok\n" ); } #endif /* MBEDTLS_X509_CSR_PARSE_C */ /* * 1.1. Load the keys */ if( !opt.selfsign && !strlen( opt.request_file ) ) { mbedtls_printf( " . Loading the subject key ..." ); fflush( stdout ); ret = mbedtls_pk_parse_keyfile( &loaded_subject_key, opt.subject_key, opt.subject_pwd ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); } mbedtls_printf( " . Loading the issuer key ..." ); fflush( stdout ); ret = mbedtls_pk_parse_keyfile( &loaded_issuer_key, opt.issuer_key, opt.issuer_pwd ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned -x%02x - %s\n\n", -ret, buf ); goto exit; } // Check if key and issuer certificate match // if( strlen( opt.issuer_crt ) ) { if( !mbedtls_pk_can_do( &issuer_crt.pk, MBEDTLS_PK_RSA ) || mbedtls_mpi_cmp_mpi( &mbedtls_pk_rsa( issuer_crt.pk )->N, &mbedtls_pk_rsa( *issuer_key )->N ) != 0 || mbedtls_mpi_cmp_mpi( &mbedtls_pk_rsa( issuer_crt.pk )->E, &mbedtls_pk_rsa( *issuer_key )->E ) != 0 ) { mbedtls_printf( " failed\n ! issuer_key does not match issuer certificate\n\n" ); ret = -1; goto exit; } } mbedtls_printf( " ok\n" ); if( opt.selfsign ) { opt.subject_name = opt.issuer_name; subject_key = issuer_key; } mbedtls_x509write_crt_set_subject_key( &crt, subject_key ); mbedtls_x509write_crt_set_issuer_key( &crt, issuer_key ); /* * 1.0. Check the names for validity */ if( ( ret = mbedtls_x509write_crt_set_subject_name( &crt, opt.subject_name ) ) != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_subject_name returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } if( ( ret = mbedtls_x509write_crt_set_issuer_name( &crt, opt.issuer_name ) ) != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_issuer_name returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " . Setting certificate values ..." ); fflush( stdout ); ret = mbedtls_x509write_crt_set_serial( &crt, &serial ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_serial returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } ret = mbedtls_x509write_crt_set_validity( &crt, opt.not_before, opt.not_after ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_validity returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); mbedtls_printf( " . Adding the Basic Constraints extension ..." ); fflush( stdout ); ret = mbedtls_x509write_crt_set_basic_constraints( &crt, opt.is_ca, opt.max_pathlen ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! x509write_crt_set_basic_contraints returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); #if defined(MBEDTLS_SHA1_C) mbedtls_printf( " . Adding the Subject Key Identifier ..." ); fflush( stdout ); ret = mbedtls_x509write_crt_set_subject_key_identifier( &crt ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_subject_key_identifier returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); mbedtls_printf( " . Adding the Authority Key Identifier ..." ); fflush( stdout ); ret = mbedtls_x509write_crt_set_authority_key_identifier( &crt ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_authority_key_identifier returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); #endif /* MBEDTLS_SHA1_C */ if( opt.key_usage ) { mbedtls_printf( " . Adding the Key Usage extension ..." ); fflush( stdout ); ret = mbedtls_x509write_crt_set_key_usage( &crt, opt.key_usage ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_key_usage returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); } if( opt.ns_cert_type ) { mbedtls_printf( " . Adding the NS Cert Type extension ..." ); fflush( stdout ); ret = mbedtls_x509write_crt_set_ns_cert_type( &crt, opt.ns_cert_type ); if( ret != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_ns_cert_type returned -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); } /* * 1.2. Writing the request */ mbedtls_printf( " . Writing the certificate..." ); fflush( stdout ); if( ( ret = write_certificate( &crt, opt.output_file, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_strerror( ret, buf, 1024 ); mbedtls_printf( " failed\n ! write_certifcate -0x%02x - %s\n\n", -ret, buf ); goto exit; } mbedtls_printf( " ok\n" ); exit: mbedtls_x509write_crt_free( &crt ); mbedtls_pk_free( &loaded_subject_key ); mbedtls_pk_free( &loaded_issuer_key ); mbedtls_mpi_free( &serial ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
/* * Sliding-window exponentiation: Z = X^Y mod M (HAC 14.85) * * _Rinv is optional pre-calculated version of Rinv (via calculate_rinv()). * * (See RSA Accelerator section in Technical Reference for more about Mprime, Rinv) * */ int mbedtls_mpi_exp_mod( mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi* Y, const mbedtls_mpi* M, mbedtls_mpi* _Rinv ) { int ret = 0; size_t z_words = hardware_words_needed(Z); size_t x_words = hardware_words_needed(X); size_t y_words = hardware_words_needed(Y); size_t m_words = hardware_words_needed(M); size_t num_words; mbedtls_mpi Rinv_new; /* used if _Rinv == NULL */ mbedtls_mpi *Rinv; /* points to _Rinv (if not NULL) othwerwise &RR_new */ mbedtls_mpi_uint Mprime; /* "all numbers must be the same length", so choose longest number as cardinal length of operation... */ num_words = z_words; if (x_words > num_words) { num_words = x_words; } if (y_words > num_words) { num_words = y_words; } if (m_words > num_words) { num_words = m_words; } if (num_words * 32 > 4096) { return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; } /* Determine RR pointer, either _RR for cached value or local RR_new */ if (_Rinv == NULL) { mbedtls_mpi_init(&Rinv_new); Rinv = &Rinv_new; } else { Rinv = _Rinv; } if (Rinv->p == NULL) { MBEDTLS_MPI_CHK(calculate_rinv(Rinv, M, num_words)); } Mprime = modular_inverse(M); esp_mpi_acquire_hardware(); /* "mode" register loaded with number of 512-bit blocks, minus 1 */ REG_WRITE(RSA_MODEXP_MODE_REG, (num_words / 16) - 1); /* Load M, X, Rinv, M-prime (M-prime is mod 2^32) */ mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words); mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, num_words); mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, num_words); mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Rinv, num_words); REG_WRITE(RSA_M_DASH_REG, Mprime); execute_op(RSA_START_MODEXP_REG); ret = mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, num_words); esp_mpi_release_hardware(); cleanup: if (_Rinv == NULL) { mbedtls_mpi_free(&Rinv_new); } return ret; }
/* * Generate an RSA keypair */ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, unsigned int nbits, int exponent ) { int ret; mbedtls_mpi P1, Q1, H, G; if( f_rng == NULL || nbits < 128 || exponent < 3 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G ); /* * find primes P and Q with Q < P so that: * GCD( E, (P-1)*(Q-1) ) == 1 */ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); do { MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0, f_rng, p_rng ) ); if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) mbedtls_mpi_swap( &ctx->P, &ctx->Q ); if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) continue; MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); if( mbedtls_mpi_bitlen( &ctx->N ) != nbits ) continue; MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); } while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ); /* * D = E^-1 mod ((P-1)*(Q-1)) * DP = D mod (P - 1) * DQ = D mod (Q - 1) * QP = Q^-1 mod P */ MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); ctx->len = ( mbedtls_mpi_bitlen( &ctx->N ) + 7 ) >> 3; cleanup: mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G ); if( ret != 0 ) { mbedtls_rsa_free( ctx ); return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret ); } return( 0 ); }
int main( int argc, char **argv ) { int ret = 1; mbedtls_mpi G, P, Q; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; const char *pers = "dh_genprime"; FILE *fout; int nbits = DFL_BITS; int i; char *p, *q; mbedtls_mpi_init( &G ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); mbedtls_ctr_drbg_init( &ctr_drbg ); mbedtls_entropy_init( &entropy ); if( argc == 0 ) { usage: mbedtls_printf( USAGE ); return( 1 ); } for( i = 1; i < argc; i++ ) { p = argv[i]; if( ( q = strchr( p, '=' ) ) == NULL ) goto usage; *q++ = '\0'; if( strcmp( p, "bits" ) == 0 ) { nbits = atoi( q ); if( nbits < 0 || nbits > MBEDTLS_MPI_MAX_BITS ) goto usage; } else goto usage; } if( ( ret = mbedtls_mpi_read_string( &G, 10, GENERATOR ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_read_string returned %d\n", ret ); goto exit; } mbedtls_printf( " ! Generating large primes may take minutes!\n" ); mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); goto exit; } mbedtls_printf( " ok\n . Generating the modulus, please wait..." ); fflush( stdout ); /* * This can take a long time... */ if( ( ret = mbedtls_mpi_gen_prime( &P, nbits, 1, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_gen_prime returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n . Verifying that Q = (P-1)/2 is prime..." ); fflush( stdout ); if( ( ret = mbedtls_mpi_sub_int( &Q, &P, 1 ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_sub_int returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_mpi_div_int( &Q, NULL, &Q, 2 ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_div_int returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_mpi_is_prime( &Q, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_is_prime returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n . Exporting the value in dh_prime.txt..." ); fflush( stdout ); if( ( fout = fopen( "dh_prime.txt", "wb+" ) ) == NULL ) { ret = 1; mbedtls_printf( " failed\n ! Could not create dh_prime.txt\n\n" ); goto exit; } if( ( ret = mbedtls_mpi_write_file( "P = ", &P, 16, fout ) != 0 ) || ( ret = mbedtls_mpi_write_file( "G = ", &G, 16, fout ) != 0 ) ) { mbedtls_printf( " failed\n ! mbedtls_mpi_write_file returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n\n" ); fclose( fout ); exit: mbedtls_mpi_free( &G ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) mbedtls_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
/* * Compute ECDSA signature of a hashed message (SEC1 4.1.3) * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) */ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret, key_tries, sign_tries; int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries; mbedtls_ecp_point R; mbedtls_mpi k, e, t; mbedtls_mpi *pk = &k, *pr = r; /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ if( grp->N.p == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); /* Make sure d is in range 1..n-1 */ if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) return( MBEDTLS_ERR_ECP_INVALID_KEY ); mbedtls_ecp_point_init( &R ); mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); ECDSA_RS_ENTER( sig ); #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->sig != NULL ) { /* redirect to our context */ p_sign_tries = &rs_ctx->sig->sign_tries; p_key_tries = &rs_ctx->sig->key_tries; pk = &rs_ctx->sig->k; pr = &rs_ctx->sig->r; /* jump to current step */ if( rs_ctx->sig->state == ecdsa_sig_mul ) goto mul; if( rs_ctx->sig->state == ecdsa_sig_modn ) goto modn; } #endif /* MBEDTLS_ECP_RESTARTABLE */ *p_sign_tries = 0; do { if( *p_sign_tries++ > 10 ) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; } /* * Steps 1-3: generate a suitable ephemeral keypair * and set r = xR mod n */ *p_key_tries = 0; do { if( *p_key_tries++ > 10 ) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; } MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) ); #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->sig != NULL ) rs_ctx->sig->state = ecdsa_sig_mul; mul: #endif MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G, f_rng, p_rng, ECDSA_RS_ECP ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) ); } while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 ); #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->sig != NULL ) rs_ctx->sig->state = ecdsa_sig_modn; modn: #endif /* * Accounting for everything up to the end of the loop * (step 6, but checking now avoids saving e and t) */ ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 ); /* * Step 5: derive MPI from hashed message */ MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); /* * Generate a random value to blind inv_mod in next step, * avoiding a potential timing leak. */ MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng, p_rng ) ); /* * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n */ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); } while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->sig != NULL ) mbedtls_mpi_copy( r, pr ); #endif cleanup: mbedtls_ecp_point_free( &R ); mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); ECDSA_RS_LEAVE( sig ); return( ret ); }
/* * Deterministic signature wrapper */ static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, mbedtls_md_type_t md_alg, mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret; mbedtls_hmac_drbg_context rng_ctx; mbedtls_hmac_drbg_context *p_rng = &rng_ctx; unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; size_t grp_len = ( grp->nbits + 7 ) / 8; const mbedtls_md_info_t *md_info; mbedtls_mpi h; if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); mbedtls_mpi_init( &h ); mbedtls_hmac_drbg_init( &rng_ctx ); ECDSA_RS_ENTER( det ); #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->det != NULL ) { /* redirect to our context */ p_rng = &rs_ctx->det->rng_ctx; /* jump to current step */ if( rs_ctx->det->state == ecdsa_det_sign ) goto sign; } #endif /* MBEDTLS_ECP_RESTARTABLE */ /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len ); #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->det != NULL ) rs_ctx->det->state = ecdsa_det_sign; sign: #endif #if defined(MBEDTLS_ECDSA_SIGN_ALT) ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, mbedtls_hmac_drbg_random, p_rng ); #else ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen, mbedtls_hmac_drbg_random, p_rng, rs_ctx ); #endif /* MBEDTLS_ECDSA_SIGN_ALT */ cleanup: mbedtls_hmac_drbg_free( &rng_ctx ); mbedtls_mpi_free( &h ); ECDSA_RS_LEAVE( det ); return( ret ); }
/* * Parse DHM parameters */ int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, size_t dhminlen ) { int ret; size_t len; unsigned char *p, *end; #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_context pem; mbedtls_pem_init( &pem ); /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' ) ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; else ret = mbedtls_pem_read_buffer( &pem, "-----BEGIN DH PARAMETERS-----", "-----END DH PARAMETERS-----", dhmin, NULL, 0, &dhminlen ); if( ret == 0 ) { /* * Was PEM encoded */ dhminlen = pem.buflen; } else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) goto exit; p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; #else p = (unsigned char *) dhmin; #endif /* MBEDTLS_PEM_PARSE_C */ end = p + dhminlen; /* * DHParams ::= SEQUENCE { * prime INTEGER, -- P * generator INTEGER, -- g * privateValueLength INTEGER OPTIONAL * } */ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) { ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; goto exit; } end = p + len; if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) { ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; goto exit; } if( p != end ) { /* This might be the optional privateValueLength. * If so, we can cleanly discard it */ mbedtls_mpi rec; mbedtls_mpi_init( &rec ); ret = mbedtls_asn1_get_mpi( &p, end, &rec ); mbedtls_mpi_free( &rec ); if ( ret != 0 ) { ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; goto exit; } if ( p != end ) { ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; goto exit; } } ret = 0; dhm->len = mbedtls_mpi_size( &dhm->P ); exit: #if defined(MBEDTLS_PEM_PARSE_C) mbedtls_pem_free( &pem ); #endif if( ret != 0 ) mbedtls_dhm_free( dhm ); return( ret ); }
int main( void ) { int ret; mbedtls_mpi E, P, Q, N, H, D, X, Y, Z; mbedtls_mpi_init( &E ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &H ); mbedtls_mpi_init( &D ); mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P, 10, "2789" ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &Q, 10, "3203" ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 10, "257" ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &N, &P, &Q ) ); mbedtls_printf( "\n Public key:\n\n" ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " N = ", &N, 10, NULL ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " E = ", &E, 10, NULL ) ); mbedtls_printf( "\n Private key:\n\n" ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " P = ", &P, 10, NULL ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " Q = ", &Q, 10, NULL ) ); #if defined(MBEDTLS_GENPRIME) MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P, &P, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q, &Q, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P, &Q ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &D, &E, &H ) ); mbedtls_mpi_write_file( " D = E^-1 mod (P-1)*(Q-1) = ", &D, 10, NULL ); #else mbedtls_printf("\nTest skipped (MBEDTLS_GENPRIME not defined).\n\n"); #endif MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &X, 10, "55555" ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &Y, &X, &E, &N, NULL ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &Z, &Y, &D, &N, NULL ) ); mbedtls_printf( "\n RSA operation:\n\n" ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " X (plaintext) = ", &X, 10, NULL ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " Y (ciphertext) = X^E mod N = ", &Y, 10, NULL ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_file( " Z (decrypted) = Y^D mod N = ", &Z, 10, NULL ) ); mbedtls_printf( "\n" ); cleanup: mbedtls_mpi_free( &E ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &D ); mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); if( ret != 0 ) { mbedtls_printf( "\nAn error occurred.\n" ); ret = 1; } #if defined(_WIN32) mbedtls_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
/* * Init verify restart sub-context */ static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx ) { mbedtls_mpi_init( &ctx->u1 ); mbedtls_mpi_init( &ctx->u2 ); ctx->state = ecdsa_ver_init; }