I am doing active authentication of ePassports according to ICAO 9303 standard (part11).
- Send a challenge to the chip, the chip signs it using its private key (stored inside the chip, not readable)
- The chip sends the siganture .
- You then verify the signature using the public key (can be read from the chip)
There's two possible signature Algorithms: RSA (RSA-SHA1, RSA-PSS, RSA-SHA224, RSA-SHA256, RSA-SHA512) and ECDSA.
In section 6.1.2.3 of ICAO9303 part 11 it reads about ECDSA: " For ECDSA, the plain signature format according to TR-03111 SHALL be used. Only prime curves with uncompressed points SHALL be used. A hash algorithm, whose output length is of the same length or shorter than the length of the ECDSA key in use, SHALL be used."
What I don't quite get is how do I use the ECDSA signature in this plain format with OpenSSL?
In the following code EVP_DigestVerifyFinal
returns -1. How can I bring the signature oSIG
from plain format to DER format?
bool doAA(std::vector<unsigned char> oRND, std::vector<unsigned char> oSIG, std::vector<unsigned char> oPKEY)
{
EVP_PKEY* m_pPubkey;
BIO* keyBio = BIO_new_mem_buf(&oPKEY[0], (int)oPKEY.size());
m_pPubkey = d2i_PUBKEY_bio(keyBio, NULL);
BIO_free(keyBio);
if (NULL == m_pPubkey)
{
std::cout << "Error Public key is NULL" << std::endl;
return false;
}
// check if ECDSA signature and then verify
int nRes = 0;
int type = EVP_PKEY_base_id(m_pPubkey);
if (type == EVP_PKEY_EC)
{
EVP_MD_CTX* ctx = EVP_MD_CTX_create();
nRes = EVP_DigestVerifyInit(ctx, NULL, EVP_sha1(), NULL, m_pPubkey);
if (1 != nRes)
{
EVP_MD_CTX_cleanup(ctx);
std::cout << "Error EVP_DigestVerifyInit" << std::endl;
return false;
}
nRes = EVP_DigestVerifyUpdate(ctx, &oRND[0], oRND.size());
if (1 != nRes)
{
EVP_MD_CTX_cleanup(ctx);
std::cout << "Error EVP_DigestVerifyUpdate" << std::endl;
return false;
}
nRes = EVP_DigestVerifyFinal(ctx, &oSIG[0], oSIG.size());
EVP_MD_CTX_cleanup(ctx);
if (nRes < 0)
{
std::cout << "Error EVP_DigestVerifyFinal failed" << std::endl;
return false;
}
else if (nRes == 0)
{
std::cout << "Error EVP_DigestVerifyFinal: Signature could not be verified" << std::endl;
return false;
}
}
else
{
std::cout << "Not a ECDSA Signature" << std::endl;
return false;
}
return nRes == 1;
}
EDIT: This is the error I get: error:0D07207B:lib(13):func(114):reason(123)