Ensuring that X509 Basic Constraint is set when CA:FALSE

This commit is contained in:
Lealem Amedie
2022-06-16 08:46:52 -07:00
parent 9f2e3a2405
commit 5e63740c6c
4 changed files with 108 additions and 11 deletions

View File

@ -8148,6 +8148,7 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref(
if (ret == WOLFSSL_SUCCESS) {
cert->version = req->version;
cert->isCA = req->isCa;
cert->basicConstSet = req->basicConstSet;
#ifdef WOLFSSL_CERT_EXT
if (req->subjKeyIdSz != 0) {
XMEMCPY(cert->skid, req->subjKeyId, req->subjKeyIdSz);
@ -8239,6 +8240,7 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref(
cert->sigType = wolfSSL_X509_get_signature_type(x509);
cert->keyType = x509->pubKeyOID;
cert->isCA = wolfSSL_X509_get_isCA(x509);
cert->basicConstSet = x509->basicConstSet;
#ifdef WOLFSSL_CERT_EXT
if (x509->subjKeyIdSz <= CTC_MAX_SKID_SIZE) {

View File

@ -38593,7 +38593,54 @@ static void test_wolfSSL_PEM_write_bio_X509(void)
expectedLen = 1688;
AssertIntEQ(wolfSSL_BIO_get_len(output), expectedLen);
/* Reset buffers and x509 */
BIO_free(input);
BIO_free(output);
X509_free(x509a);
/* test CA and basicConstSet values are encoded when
* the cert is a CA */
AssertNotNull(input = BIO_new_file(
"certs/server-cert.pem", "rb"));
/* read PEM into X509 struct */
AssertNotNull(PEM_read_bio_X509(input, &x509a, NULL, NULL));
/* write X509 back to PEM BIO */
AssertNotNull(output = BIO_new(wolfSSL_BIO_s_mem()));
AssertIntEQ(PEM_write_bio_X509(output, x509a), WOLFSSL_SUCCESS);
/* read exported X509 PEM back into struct, ensure isCa and
* basicConstSet values are maintained */
AssertNotNull(PEM_read_bio_X509(output, &x509b, NULL, NULL));
AssertIntEQ(x509b->isCa, 1);
AssertIntEQ(x509b->basicConstSet, 1);
X509_free(x509a);
X509_free(x509b);
BIO_free(input);
BIO_free(output);
/* test CA and basicConstSet values are encoded when
* the cert is not CA */
AssertNotNull(input = BIO_new_file(
"certs/client-uri-cert.pem", "rb"));
/* read PEM into X509 struct */
AssertNotNull(PEM_read_bio_X509(input, &x509a, NULL, NULL));
/* write X509 back to PEM BIO */
AssertNotNull(output = BIO_new(wolfSSL_BIO_s_mem()));
AssertIntEQ(PEM_write_bio_X509(output, x509a), WOLFSSL_SUCCESS);
/* read exported X509 PEM back into struct, ensure isCa and
* basicConstSet values are maintained */
AssertNotNull(PEM_read_bio_X509(output, &x509b, NULL, NULL));
AssertIntEQ(x509b->isCa, 0);
AssertIntEQ(x509b->basicConstSet, 1);
X509_free(x509a);
X509_free(x509b);
BIO_free(input);
BIO_free(output);

View File

@ -22041,21 +22041,46 @@ static int SetExtensionsHeader(byte* out, word32 outSz, int extSz)
}
/* encode CA basic constraint true, return total bytes written */
/* encode CA basic constraints true
* return total bytes written */
static int SetCa(byte* out, word32 outSz)
{
const byte ca[] = { 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
0x05, 0x30, 0x03, 0x01, 0x01, 0xff };
/* ASN1->DER sequence for Basic Constraints True */
const byte caBasicConstASN1[] = {
0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
0x05, 0x30, 0x03, 0x01, 0x01, 0xff
};
if (out == NULL)
return BAD_FUNC_ARG;
if (outSz < sizeof(ca))
if (outSz < sizeof(caBasicConstASN1))
return BUFFER_E;
XMEMCPY(out, ca, sizeof(ca));
XMEMCPY(out, caBasicConstASN1, sizeof(caBasicConstASN1));
return (int)sizeof(ca);
return (int)sizeof(caBasicConstASN1);
}
/* encode basic constraints without CA Boolean
* return total bytes written */
static int SetBC(byte* out, word32 outSz)
{
/* ASN1->DER sequence for Basic Constraint without CA Boolean */
const byte BasicConstASN1[] = {
0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
0x02, 0x30, 0x00
};
if (out == NULL)
return BAD_FUNC_ARG;
if (outSz < sizeof(BasicConstASN1))
return BUFFER_E;
XMEMCPY(out, BasicConstASN1, sizeof(BasicConstASN1));
return (int)sizeof(BasicConstASN1);
}
#endif
@ -23589,6 +23614,12 @@ static int EncodeExtensions(Cert* cert, byte* output, word32 maxSz,
/* TODO: consider adding path length field in Cert. */
dataASN[CERTEXTSASN_IDX_BC_PATHLEN].noOut = 1;
}
else if (cert->basicConstSet) {
/* Set Basic Constraints to be a non Certificate Authority. */
SetASN_Buffer(&dataASN[CERTEXTSASN_IDX_BC_OID], bcOID, sizeof(bcOID));
dataASN[CERTEXTSASN_IDX_BC_CA].noOut = 1;
dataASN[CERTEXTSASN_IDX_BC_PATHLEN].noOut = 1;
}
else {
/* Don't write out Basic Constraints extension items. */
SetASNItem_NoOut(dataASN, CERTEXTSASN_IDX_BC_SEQ,
@ -24172,7 +24203,7 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
/* set the extensions */
der->extensionsSz = 0;
/* CA */
/* Set CA */
if (cert->isCA) {
der->caSz = SetCa(der->ca, sizeof(der->ca));
if (der->caSz <= 0)
@ -24180,6 +24211,14 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
der->extensionsSz += der->caSz;
}
/* Set Basic Constraint */
else if (cert->basicConstSet) {
der->caSz = SetBC(der->ca, sizeof(der->ca));
if (der->caSz <= 0)
return EXTENSIONS_E;
der->extensionsSz += der->caSz;
}
else
der->caSz = 0;
@ -25335,7 +25374,7 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey,
/* set the extensions */
der->extensionsSz = 0;
/* CA */
/* Set CA */
if (cert->isCA) {
der->caSz = SetCa(der->ca, sizeof(der->ca));
if (der->caSz <= 0)
@ -25343,6 +25382,14 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey,
der->extensionsSz += der->caSz;
}
/* Set Basic Constraint */
else if (cert->basicConstSet) {
der->caSz = SetBC(der->ca, sizeof(der->ca));
if (der->caSz <= 0)
return EXTENSIONS_E;
der->extensionsSz += der->caSz;
}
else
der->caSz = 0;

View File

@ -446,6 +446,7 @@ typedef struct Cert {
void* decodedCert; /* internal DecodedCert allocated from heap */
byte* der; /* Pointer to buffer of current DecodedCert cache */
void* heap; /* heap hint */
byte basicConstSet:1; /* Indicator for when Basic Constaint is set */
} Cert;