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; return WOLFSSL_FATAL_ERROR;
} }
/* Use the public key to verify the signature. Note: this only verifies /* Use the public key to verify the signature. Note: this only verifies
* the certificate signature. * the certificate signature.
* returns WOLFSSL_SUCCESS on successful signature verification */ * 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; int ret;
const byte* der; const byte* der;
@ -23906,13 +23905,31 @@ int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey)
return WOLFSSL_FATAL_ERROR; return WOLFSSL_FATAL_ERROR;
} }
ret = CheckCertSignaturePubKey(der, derSz, x509->heap, #ifdef WOLFSSL_CERT_REQ
(unsigned char*)pkey->pkey.ptr, pkey->pkey_sz, type); 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) { if (ret == 0) {
return WOLFSSL_SUCCESS; return WOLFSSL_SUCCESS;
} }
return WOLFSSL_FAILURE; 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 */ #endif /* !NO_CERTS */
#if !defined(NO_FILESYSTEM) #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) 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"); WOLFSSL_ENTER("wolfSSL_X509_set_pubkey");
if (cert == NULL || pkey == NULL) if (cert == NULL || pkey == NULL)
@ -49657,15 +49675,29 @@ int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey)
else else
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
p = (byte*)XMALLOC(pkey->pkey_sz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (pkey->type == EVP_PKEY_RSA) {
if (p == NULL) /* Public and private key formats differ. Make sure to put in the
return WOLFSSL_FAILURE; * 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) if (cert->pubKey.buffer != NULL)
XFREE(cert->pubKey.buffer, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); XFREE(cert->pubKey.buffer, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY);
cert->pubKey.buffer = p; cert->pubKey.buffer = p;
XMEMCPY(cert->pubKey.buffer, pkey->pkey.ptr, pkey->pkey_sz); XMEMCPY(cert->pubKey.buffer, pkey->pkey.ptr, pkey->pkey_sz);
cert->pubKey.length = pkey->pkey_sz; cert->pubKey.length = pkey->pkey_sz;
}
return WOLFSSL_SUCCESS; return WOLFSSL_SUCCESS;
} }

View File

@ -37884,12 +37884,23 @@ static void test_wolfSSL_d2i_X509_REQ(void)
{ {
const char* csrFile = "./csr.signed.der"; const char* csrFile = "./csr.signed.der";
BIO* bio = NULL; BIO* bio = NULL;
X509* x509 = NULL; X509* req = NULL;
EVP_PKEY *pub_key = NULL;
AssertNotNull(bio = BIO_new_file(csrFile, "rb")); 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); 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 /* Only quick step through the certificate to find fields that are then used
* in certificate signature verification. * in certificate signature verification.
* Must use the signature OID from the signed part of the certificate. * 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 * This is only for minimizing dynamic memory usage during TLS certificate
* chain processing. * 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 * OCSP Only: alt lookup using subject and pub key w/o sig check
*/ */
static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap, 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 #ifndef WOLFSSL_SMALL_STACK
SignatureCtx sigCtx[1]; SignatureCtx sigCtx[1];
@ -9177,13 +9178,14 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
idx += len; idx += len;
/* signature */ /* signature */
if (GetAlgoId(cert, &idx, &signatureOID, oidSigType, certSz) < 0) if (!req &&
GetAlgoId(cert, &idx, &signatureOID, oidSigType, certSz) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
} }
if (ret == 0) { if (ret == 0) {
issuerIdx = idx; issuerIdx = idx;
/* issuer */ /* issuer for cert or subject for csr */
if (GetSequence(cert, &idx, &len, certSz) < 0) if (GetSequence(cert, &idx, &len, certSz) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
} }
@ -9191,14 +9193,14 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
issuerSz = len + idx - issuerIdx; issuerSz = len + idx - issuerIdx;
} }
#ifndef NO_SKID #ifndef NO_SKID
if (ret == 0) { if (!req && ret == 0) {
idx += len; idx += len;
/* validity */ /* validity */
if (GetSequence(cert, &idx, &len, certSz) < 0) if (GetSequence(cert, &idx, &len, certSz) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
} }
if (ret == 0) { if (!req && ret == 0) {
idx += len; idx += len;
/* subject */ /* subject */
@ -9212,123 +9214,137 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
if (GetSequence(cert, &idx, &len, certSz) < 0) if (GetSequence(cert, &idx, &len, certSz) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
} }
if (ret == 0) { if (req && ret == 0) {
idx += len; idx += len;
if ((idx + 1) > certSz) /* attributes */
ret = BUFFER_E; if (GetASNHeader_ex(cert,
} ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED, &idx,
if (ret == 0) { &len, certSz, 1) < 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; ret = ASN_PARSE_E;
}
if (!req) {
if (ret == 0) { if (ret == 0) {
if (GetSequence(cert, &idx, &extLen, certSz) < 0) idx += len;
ret = ASN_PARSE_E;
if ((idx + 1) > certSz)
ret = BUFFER_E;
} }
if (ret == 0) { if (ret == 0) {
extEndIdx = idx + extLen; /* issuerUniqueID - optional */
localIdx = idx;
/* Check each extension for the ones we want. */ if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
while (ret == 0 && idx < extEndIdx) { if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) {
if (GetSequence(cert, &idx, &len, certSz) < 0) idx++;
ret = ASN_PARSE_E; if (GetLength(cert, &idx, &len, certSz) < 0)
if (ret == 0) {
extIdx = idx;
if (GetObjectId(cert, &extIdx, &oid, oidCertExtType,
certSz) < 0) {
ret = ASN_PARSE_E; 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 (ret == 0) {
if ((extIdx + 1) > certSz) localIdx = extIdx;
ret = BUFFER_E; if (GetASNTag(cert, &localIdx, &tag, certSz) == 0 &&
} tag == ASN_BOOLEAN) {
} if (GetBoolean(cert, &extIdx, certSz) < 0)
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)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
if (ret == 0) { }
extAuthKeyIdSet = 1; }
if (extLen == KEYID_SIZE) if (ret == 0) {
XMEMCPY(hash, cert + extIdx, extLen); if (GetOctetString(cert, &extIdx, &extLen, certSz) < 0)
else { ret = ASN_PARSE_E;
ret = CalcHashId(cert + extIdx, extLen, }
hash);
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: default:
break; break;
}
} }
idx += len;
} }
idx += len;
} }
} }
} }
else if (ret == 0) {
idx += len;
}
if (ret == 0 && pubKey == NULL) { if (ret == 0 && pubKey == NULL) {
if (extAuthKeyIdSet) if (extAuthKeyIdSet)
@ -9354,6 +9370,9 @@ static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
/* signatureAlgorithm */ /* signatureAlgorithm */
if (GetAlgoId(cert, &idx, &oid, oidSigType, certSz) < 0) if (GetAlgoId(cert, &idx, &oid, oidSigType, certSz) < 0)
ret = ASN_PARSE_E; ret = ASN_PARSE_E;
/* In CSR signature data is not present in body */
if (req)
signatureOID = oid;
} }
if (ret == 0) { if (ret == 0) {
if (oid != signatureOID) if (oid != signatureOID)
@ -9398,15 +9417,23 @@ int CheckCertSignaturePubKey(const byte* cert, word32 certSz, void* heap,
const byte* pubKey, word32 pubKeySz, int pubKeyOID) const byte* pubKey, word32 pubKeySz, int pubKeyOID)
{ {
return CheckCertSignature_ex(cert, certSz, heap, NULL, 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 */ #endif /* OPENSSL_EXTRA */
#ifdef WOLFSSL_SMALL_CERT_VERIFY #ifdef WOLFSSL_SMALL_CERT_VERIFY
/* Call CheckCertSignature_ex using a certificate manager (cm) /* Call CheckCertSignature_ex using a certificate manager (cm)
*/ */
int CheckCertSignature(const byte* cert, word32 certSz, void* heap, void* 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 */
#endif /* WOLFSSL_SMALL_CERT_VERIFY || OPENSSL_EXTRA */ #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_error_string wolfSSL_X509_verify_cert_error_string
#define X509_verify_cert wolfSSL_X509_verify_cert #define X509_verify_cert wolfSSL_X509_verify_cert
#define X509_verify wolfSSL_X509_verify #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_private_key wolfSSL_X509_check_private_key
#define X509_check_ca wolfSSL_X509_check_ca #define X509_check_ca wolfSSL_X509_check_ca
#define X509_check_host wolfSSL_X509_check_host #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_X509*, unsigned char*, int*);
WOLFSSL_API int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey); 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_API int wolfSSL_X509_set_subject_name(WOLFSSL_X509*,
WOLFSSL_X509_NAME*); WOLFSSL_X509_NAME*);
WOLFSSL_API int wolfSSL_X509_set_issuer_name(WOLFSSL_X509*, 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_API int CheckCertSignature(const byte*,word32,void*,void* cm);
WOLFSSL_LOCAL int CheckCertSignaturePubKey(const byte* cert, word32 certSz, WOLFSSL_LOCAL int CheckCertSignaturePubKey(const byte* cert, word32 certSz,
void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID); 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, WOLFSSL_LOCAL int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz,
int sigAlgoType); int sigAlgoType);
WOLFSSL_LOCAL int ParseCertRelative(DecodedCert*,int type,int verify,void* cm); WOLFSSL_LOCAL int ParseCertRelative(DecodedCert*,int type,int verify,void* cm);