Implement wolfSSL_X509_REQ_verify

This commit is contained in:
Juliusz Sosinowicz
2020-07-21 23:05:04 +02:00
parent 4aa30d0bde
commit be98404b3b
6 changed files with 199 additions and 122 deletions

View File

@ -23867,11 +23867,10 @@ int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx)
return WOLFSSL_FATAL_ERROR;
}
/* Use the public key to verify the signature. Note: this only verifies
* the certificate signature.
* returns WOLFSSL_SUCCESS on successful signature verification */
int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey)
static int wolfSSL_X509_X509_REQ_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey, int req)
{
int ret;
const byte* der;
@ -23906,13 +23905,31 @@ int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey)
return WOLFSSL_FATAL_ERROR;
}
ret = CheckCertSignaturePubKey(der, derSz, x509->heap,
(unsigned char*)pkey->pkey.ptr, pkey->pkey_sz, type);
#ifdef WOLFSSL_CERT_REQ
if (req)
ret = CheckCSRSignaturePubKey(der, derSz, x509->heap,
(unsigned char*)pkey->pkey.ptr, pkey->pkey_sz, type);
else
#endif
ret = CheckCertSignaturePubKey(der, derSz, x509->heap,
(unsigned char*)pkey->pkey.ptr, pkey->pkey_sz, type);
if (ret == 0) {
return WOLFSSL_SUCCESS;
}
return WOLFSSL_FAILURE;
}
int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey)
{
return wolfSSL_X509_X509_REQ_verify(x509, pkey, 0);
}
#ifdef WOLFSSL_CERT_REQ
int wolfSSL_X509_REQ_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey)
{
return wolfSSL_X509_X509_REQ_verify(x509, pkey, 1);
}
#endif /* WOLFSSL_CERT_REQ */
#endif /* !NO_CERTS */
#if !defined(NO_FILESYSTEM)
@ -49644,7 +49661,8 @@ int wolfSSL_X509_set_serialNumber(WOLFSSL_X509* x509, WOLFSSL_ASN1_INTEGER* s)
int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey)
{
byte* p;
byte* p = NULL;
int pLen;
WOLFSSL_ENTER("wolfSSL_X509_set_pubkey");
if (cert == NULL || pkey == NULL)
@ -49657,15 +49675,29 @@ int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey)
else
return WOLFSSL_FAILURE;
p = (byte*)XMALLOC(pkey->pkey_sz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if (p == NULL)
return WOLFSSL_FAILURE;
if (pkey->type == EVP_PKEY_RSA) {
/* Public and private key formats differ. Make sure to put in the
* public key format in the cert. */
if ((pLen = wolfSSL_i2d_RSAPublicKey(pkey->rsa, (const byte**)&p)) <= 0) {
WOLFSSL_MSG("wolfSSL_i2d_RSAPublicKey error");
return WOLFSSL_FAILURE;
}
if (cert->pubKey.buffer != NULL)
XFREE(cert->pubKey.buffer, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
cert->pubKey.buffer = p;
cert->pubKey.length = pLen;
}
else {
p = (byte*)XMALLOC(pkey->pkey_sz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if (p == NULL)
return WOLFSSL_FAILURE;
if (cert->pubKey.buffer != NULL)
XFREE(cert->pubKey.buffer, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
cert->pubKey.buffer = p;
XMEMCPY(cert->pubKey.buffer, pkey->pkey.ptr, pkey->pkey_sz);
cert->pubKey.length = pkey->pkey_sz;
if (cert->pubKey.buffer != NULL)
XFREE(cert->pubKey.buffer, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
cert->pubKey.buffer = p;
XMEMCPY(cert->pubKey.buffer, pkey->pkey.ptr, pkey->pkey_sz);
cert->pubKey.length = pkey->pkey_sz;
}
return WOLFSSL_SUCCESS;
}

View File

@ -37884,12 +37884,23 @@ static void test_wolfSSL_d2i_X509_REQ(void)
{
const char* csrFile = "./csr.signed.der";
BIO* bio = NULL;
X509* x509 = NULL;
X509* req = NULL;
EVP_PKEY *pub_key = NULL;
AssertNotNull(bio = BIO_new_file(csrFile, "rb"));
AssertNotNull(d2i_X509_REQ_bio(bio, &x509));
AssertNotNull(d2i_X509_REQ_bio(bio, &req));
X509_free(x509);
/*
* Extract the public key from the CSR
*/
AssertNotNull(pub_key = X509_REQ_get_pubkey(req));
/*
* Verify the signature in the CSR
*/
AssertIntEQ(X509_REQ_verify(req, pub_key), 1);
X509_free(req);
BIO_free(bio);
}

View File

@ -9093,6 +9093,7 @@ static Signer* GetCABySubjectAndPubKey(DecodedCert* cert, void* cm)
/* Only quick step through the certificate to find fields that are then used
* in certificate signature verification.
* Must use the signature OID from the signed part of the certificate.
* Works also on certificate signing requests.
*
* This is only for minimizing dynamic memory usage during TLS certificate
* chain processing.
@ -9100,7 +9101,7 @@ static Signer* GetCABySubjectAndPubKey(DecodedCert* cert, void* cm)
* OCSP Only: alt lookup using subject and pub key w/o sig check
*/
static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
void* cm, const byte* pubKey, word32 pubKeySz, int pubKeyOID)
void* cm, const byte* pubKey, word32 pubKeySz, int pubKeyOID, int req)
{
#ifndef WOLFSSL_SMALL_STACK
SignatureCtx sigCtx[1];
@ -9177,13 +9178,14 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
idx += len;
/* signature */
if (GetAlgoId(cert, &idx, &signatureOID, oidSigType, certSz) < 0)
if (!req &&
GetAlgoId(cert, &idx, &signatureOID, oidSigType, certSz) < 0)
ret = ASN_PARSE_E;
}
if (ret == 0) {
issuerIdx = idx;
/* issuer */
/* issuer for cert or subject for csr */
if (GetSequence(cert, &idx, &len, certSz) < 0)
ret = ASN_PARSE_E;
}
@ -9191,14 +9193,14 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
issuerSz = len + idx - issuerIdx;
}
#ifndef NO_SKID
if (ret == 0) {
if (!req && ret == 0) {
idx += len;
/* validity */
if (GetSequence(cert, &idx, &len, certSz) < 0)
ret = ASN_PARSE_E;
}
if (ret == 0) {
if (!req && ret == 0) {
idx += len;
/* subject */
@ -9212,123 +9214,137 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
if (GetSequence(cert, &idx, &len, certSz) < 0)
ret = ASN_PARSE_E;
}
if (ret == 0) {
if (req && ret == 0) {
idx += len;
if ((idx + 1) > certSz)
ret = BUFFER_E;
}
if (ret == 0) {
/* issuerUniqueID - optional */
localIdx = idx;
if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) {
idx++;
if (GetLength(cert, &idx, &len, certSz) < 0)
ret = ASN_PARSE_E;
idx += len;
}
}
}
if (ret == 0) {
if ((idx + 1) > certSz)
ret = BUFFER_E;
}
if (ret == 0) {
/* subjectUniqueID - optional */
localIdx = idx;
if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)) {
idx++;
if (GetLength(cert, &idx, &len, certSz) < 0)
ret = ASN_PARSE_E;
idx += len;
}
}
}
if (ret == 0) {
if ((idx + 1) > certSz)
ret = BUFFER_E;
}
/* extensions - optional */
localIdx = idx;
if (ret == 0 && GetASNTag(cert, &localIdx, &tag, certSz) == 0 &&
tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 3)) {
idx++;
if (GetLength(cert, &idx, &extLen, certSz) < 0)
/* attributes */
if (GetASNHeader_ex(cert,
ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED, &idx,
&len, certSz, 1) < 0)
ret = ASN_PARSE_E;
}
if (!req) {
if (ret == 0) {
if (GetSequence(cert, &idx, &extLen, certSz) < 0)
ret = ASN_PARSE_E;
idx += len;
if ((idx + 1) > certSz)
ret = BUFFER_E;
}
if (ret == 0) {
extEndIdx = idx + extLen;
/* Check each extension for the ones we want. */
while (ret == 0 && idx < extEndIdx) {
if (GetSequence(cert, &idx, &len, certSz) < 0)
ret = ASN_PARSE_E;
if (ret == 0) {
extIdx = idx;
if (GetObjectId(cert, &extIdx, &oid, oidCertExtType,
certSz) < 0) {
/* issuerUniqueID - optional */
localIdx = idx;
if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) {
idx++;
if (GetLength(cert, &idx, &len, certSz) < 0)
ret = ASN_PARSE_E;
idx += len;
}
}
}
if (ret == 0) {
if ((idx + 1) > certSz)
ret = BUFFER_E;
}
if (ret == 0) {
/* subjectUniqueID - optional */
localIdx = idx;
if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)) {
idx++;
if (GetLength(cert, &idx, &len, certSz) < 0)
ret = ASN_PARSE_E;
idx += len;
}
}
}
if (ret == 0) {
if ((idx + 1) > certSz)
ret = BUFFER_E;
}
/* extensions - optional */
localIdx = idx;
if (ret == 0 && GetASNTag(cert, &localIdx, &tag, certSz) == 0 &&
tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 3)) {
idx++;
if (GetLength(cert, &idx, &extLen, certSz) < 0)
ret = ASN_PARSE_E;
if (ret == 0) {
if (GetSequence(cert, &idx, &extLen, certSz) < 0)
ret = ASN_PARSE_E;
}
if (ret == 0) {
extEndIdx = idx + extLen;
/* Check each extension for the ones we want. */
while (ret == 0 && idx < extEndIdx) {
if (GetSequence(cert, &idx, &len, certSz) < 0)
ret = ASN_PARSE_E;
if (ret == 0) {
extIdx = idx;
if (GetObjectId(cert, &extIdx, &oid, oidCertExtType,
certSz) < 0) {
ret = ASN_PARSE_E;
}
if (ret == 0) {
if ((extIdx + 1) > certSz)
ret = BUFFER_E;
}
}
if (ret == 0) {
if ((extIdx + 1) > certSz)
ret = BUFFER_E;
}
}
if (ret == 0) {
localIdx = extIdx;
if (GetASNTag(cert, &localIdx, &tag, certSz) == 0 &&
tag == ASN_BOOLEAN) {
if (GetBoolean(cert, &extIdx, certSz) < 0)
ret = ASN_PARSE_E;
}
}
if (ret == 0) {
if (GetOctetString(cert, &extIdx, &extLen, certSz) < 0)
ret = ASN_PARSE_E;
}
if (ret == 0) {
switch (oid) {
case AUTH_KEY_OID:
if (GetSequence(cert, &extIdx, &extLen, certSz) < 0)
ret = ASN_PARSE_E;
if (ret == 0 && (extIdx + 1) >= certSz)
ret = BUFFER_E;
if (ret == 0 &&
GetASNTag(cert, &extIdx, &tag, certSz) == 0 &&
tag == (ASN_CONTEXT_SPECIFIC | 0)) {
if (GetLength(cert, &extIdx, &extLen, certSz) <= 0)
localIdx = extIdx;
if (GetASNTag(cert, &localIdx, &tag, certSz) == 0 &&
tag == ASN_BOOLEAN) {
if (GetBoolean(cert, &extIdx, certSz) < 0)
ret = ASN_PARSE_E;
if (ret == 0) {
extAuthKeyIdSet = 1;
if (extLen == KEYID_SIZE)
XMEMCPY(hash, cert + extIdx, extLen);
else {
ret = CalcHashId(cert + extIdx, extLen,
hash);
}
}
if (ret == 0) {
if (GetOctetString(cert, &extIdx, &extLen, certSz) < 0)
ret = ASN_PARSE_E;
}
if (ret == 0) {
switch (oid) {
case AUTH_KEY_OID:
if (GetSequence(cert, &extIdx, &extLen, certSz) < 0)
ret = ASN_PARSE_E;
if (ret == 0 && (extIdx + 1) >= certSz)
ret = BUFFER_E;
if (ret == 0 &&
GetASNTag(cert, &extIdx, &tag, certSz) == 0 &&
tag == (ASN_CONTEXT_SPECIFIC | 0)) {
if (GetLength(cert, &extIdx, &extLen, certSz) <= 0)
ret = ASN_PARSE_E;
if (ret == 0) {
extAuthKeyIdSet = 1;
if (extLen == KEYID_SIZE)
XMEMCPY(hash, cert + extIdx, extLen);
else {
ret = CalcHashId(cert + extIdx, extLen,
hash);
}
}
}
}
break;
break;
default:
break;
default:
break;
}
}
idx += len;
}
idx += len;
}
}
}
else if (ret == 0) {
idx += len;
}
if (ret == 0 && pubKey == NULL) {
if (extAuthKeyIdSet)
@ -9354,6 +9370,9 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
/* signatureAlgorithm */
if (GetAlgoId(cert, &idx, &oid, oidSigType, certSz) < 0)
ret = ASN_PARSE_E;
/* In CSR signature data is not present in body */
if (req)
signatureOID = oid;
}
if (ret == 0) {
if (oid != signatureOID)
@ -9398,15 +9417,23 @@ int CheckCertSignaturePubKey(const byte* cert, word32 certSz, void* heap,
const byte* pubKey, word32 pubKeySz, int pubKeyOID)
{
return CheckCertSignature_ex(cert, certSz, heap, NULL,
pubKey, pubKeySz, pubKeyOID);
pubKey, pubKeySz, pubKeyOID, 0);
}
#ifdef WOLFSSL_CERT_REQ
int CheckCSRSignaturePubKey(const byte* cert, word32 certSz, void* heap,
const byte* pubKey, word32 pubKeySz, int pubKeyOID)
{
return CheckCertSignature_ex(cert, certSz, heap, NULL,
pubKey, pubKeySz, pubKeyOID, 1);
}
#endif /* WOLFSSL_CERT_REQ */
#endif /* OPENSSL_EXTRA */
#ifdef WOLFSSL_SMALL_CERT_VERIFY
/* Call CheckCertSignature_ex using a certificate manager (cm)
*/
int CheckCertSignature(const byte* cert, word32 certSz, void* heap, void* cm)
{
return CheckCertSignature_ex(cert, certSz, heap, cm, NULL, 0, 0);
return CheckCertSignature_ex(cert, certSz, heap, cm, NULL, 0, 0, 0);
}
#endif /* WOLFSSL_SMALL_CERT_VERIFY */
#endif /* WOLFSSL_SMALL_CERT_VERIFY || OPENSSL_EXTRA */

View File

@ -441,7 +441,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS;
#define X509_verify_cert_error_string wolfSSL_X509_verify_cert_error_string
#define X509_verify_cert wolfSSL_X509_verify_cert
#define X509_verify wolfSSL_X509_verify
#define X509_REQ_verify wolfSSL_X509_verify
#define X509_REQ_verify wolfSSL_X509_REQ_verify
#define X509_check_private_key wolfSSL_X509_check_private_key
#define X509_check_ca wolfSSL_X509_check_ca
#define X509_check_host wolfSSL_X509_check_host

View File

@ -1377,6 +1377,9 @@ WOLFSSL_API unsigned char* wolfSSL_X509_get_subjectKeyID(
WOLFSSL_X509*, unsigned char*, int*);
WOLFSSL_API int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey);
#ifdef WOLFSSL_CERT_REQ
WOLFSSL_API int wolfSSL_X509_REQ_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey);
#endif
WOLFSSL_API int wolfSSL_X509_set_subject_name(WOLFSSL_X509*,
WOLFSSL_X509_NAME*);
WOLFSSL_API int wolfSSL_X509_set_issuer_name(WOLFSSL_X509*,

View File

@ -1043,6 +1043,10 @@ WOLFSSL_LOCAL int EncodePolicyOID(byte *out, word32 *outSz,
WOLFSSL_API int CheckCertSignature(const byte*,word32,void*,void* cm);
WOLFSSL_LOCAL int CheckCertSignaturePubKey(const byte* cert, word32 certSz,
void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID);
#ifdef WOLFSSL_CERT_REQ
WOLFSSL_LOCAL int CheckCSRSignaturePubKey(const byte* cert, word32 certSz, void* heap,
const byte* pubKey, word32 pubKeySz, int pubKeyOID);
#endif /* WOLFSSL_CERT_REQ */
WOLFSSL_LOCAL int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz,
int sigAlgoType);
WOLFSSL_LOCAL int ParseCertRelative(DecodedCert*,int type,int verify,void* cm);