3

Mbedtls can validate an x509 cert with its mbedtls_x509_crt_verify(...) function (link).

However, what I have:

  • A public/private key pair (saved in an mbedtls_pk_context).
  • A certificate I've got from a different source (thus, there is no guarantee that it does not contain any, possible intelligent modifications).

There is no problem with the validation of the certificate.

However, what if that certificate validates a different key? (What can be the result of a software problem and also a crack attempt.) Of course, such a key/cert pair will be unable for a tls handshake, but I don't think that I would need to build up a tcp connection for that.

This source (although it is for openssl scripting) makes likely, that certificate-key matching validation can happen with simply a modulus match.

There is also an mbedtls_pk_verify(...) function (ref), but it seems to me that it plays mostly with signatures. But I have no signatures, I have a cert (got in a pem format), and my key (I have also that in a pem format). Processing them into internal mbedtls data structures (mbedtls_x509_crt and mbedtls_pk_context) is not a problem, but how could I verify that they match?

peterh
  • 11,875
  • 18
  • 85
  • 108
  • 2
    Note, this question does not ask for example code, and it is not a "do my work" question. The essence of this question is: *How to verify that my `mbedtls_pk_context` and my `mbedtls_x509_cert` match*? – peterh Nov 27 '19 at 17:19

2 Answers2

2

As this security.SE answer says, for the validation is it enough, if the pubkey in the certificate and in the private key file are the same. It is because it is the only shared information common in them.

Thus, we need to dig out the public key from the mbedtls_pk_content and from the mbedtls_x509_cert and compare them.

The mbedtls has no general API call for this task, but it can be done by algorithm-specific solutions. The steps are the following. Assume that we have

mbedtls_x509_cert crt;
mbedtls_pk_context pk;

Where crt has the certificate and pk is our public-private key pair.

  1. We get the keypair from both. In the case of elliptic curve ciphers, it is being done by the mbedtls_pk_ec(...) macro. In the case of rsa, mbedtls_rsa_context(...) is needed:

    mbedtls_ecp_keypair* crt_pair = mbedtls_pk_ec(crt->pk);
    mbedtls_ecp_keypair* pk_pair = mbedtls_pk_ec(*pk);
    

Note, although crt_pair is now a keypair, only its public part will be non-zero, because the certificate has obviously no private key part. mbedtls_pk_ec(...) looks to be some macro-like thing to me, because it doesn't use a pointer to the structs, instead it uses directly a struct.

  1. Then, we compare the public keys in the keypairs:

    mbedtls_mpi *pk_pub_X = &pk_pair->Q.X;
    mbedtls_mpi *pk_pub_Y = &pk_pair->Q.Y;
    mbedtls_mpi *crt_pub_X = &crt_pair->Q.X;
    mbedtls_mpi *crt_pub_Y = &crt_pair->Q.Y;
    

In the case of other algorithms (RSA), these parts might differ, however we always need to have a set of big numbers (mbedtls_mpi), and compare these big numbers.

  1. Then, we use the mbedtls big number functionality to compare them:

    bool does_it_differ = mbedtls_mpi_cmp_mpi(pk_pub_X, crt_pub_X) || mbedtls_mpi_cmp_mpi(pk_pub_Y, crt_pub_Y);

Note: verifying the cert match is not enough to verify the cert validity, it is only required for that. The verification of the certificate can be done with the already much more pleasant and simpler mbedtls_x509_crt_verify(...) function.

peterh
  • 11,875
  • 18
  • 85
  • 108
2

I know this is an older question, but perhaps mbedtls_pk_check_pair is what you are looking for. Pass it your private/public key pair and the certificates public key.

/**
 * \brief           Check if a public-private pair of keys matches.
 *
 * \param pub       Context holding a public key.
 * \param prv       Context holding a private (and public) key.
 *
 * \return          \c 0 on success (keys were checked and match each other).
 * \return          #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not
 *                  be checked - in that case they may or may not match.
 * \return          #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid.
 * \return          Another non-zero value if the keys do not match.
 */
int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv );
Ashley Duncan
  • 825
  • 1
  • 8
  • 22