From 26a62b4b9eb7958bafcce5ce0de0a096ed77ec82 Mon Sep 17 00:00:00 2001 From: Stanislav Klima Date: Thu, 30 Jun 2022 17:16:10 +0200 Subject: [PATCH 1/6] drafted pathlen for cert struct --- wolfcrypt/src/asn.c | 55 ++++++++++++++++++++++++++++++++-- wolfssl/wolfcrypt/asn_public.h | 2 ++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 8d43acfe8..1b94cfd44 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -22749,6 +22749,31 @@ static int SetExtensionsHeader(byte* out, word32 outSz, int extSz) } +/* encode CA basic constraints true with path length + * return total bytes written */ +static int SetCaWithPathLen(byte* out, word32 outSz, char pathLen) +{ + /* ASN1->DER sequence for Basic Constraints True and path length */ + byte caPathLenBasicConstASN1[] = { + 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, + 0x08, 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, + 0x00 + }; + + if (out == NULL) + return BAD_FUNC_ARG; + + if (outSz < sizeof(caPathLenBasicConstASN1)) + return BUFFER_E; + + caPathLenBasicConstASN1[16U] = pathLen; + + XMEMCPY(out, caPathLenBasicConstASN1, sizeof(caPathLenBasicConstASN1)); + + return (int)sizeof(caPathLenBasicConstASN1); +} + + /* encode CA basic constraints true * return total bytes written */ static int SetCa(byte* out, word32 outSz) @@ -24911,8 +24936,21 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, /* set the extensions */ der->extensionsSz = 0; + /* RFC 5280 : 4.2.1.9. Basic Constraints + * The pathLenConstraint field is meaningful only if the cA boolean is + * asserted and the key usage extension, if present, asserts the + * keyCertSign bit */ + /* Set CA and path length */ + if ((cert->isCA) && (cert->pathLen) && + ((cert->keyUsage & KEYUSE_KEY_CERT_SIGN) || (!cert->keyUsage))) { + der->caSz = SetCaWithPathLen(der->ca, sizeof(der->ca), cert->pathLen); + if (der->caSz <= 0) + return CA_TRUE_E; + + der->extensionsSz += der->caSz; + } /* Set CA */ - if (cert->isCA) { + else if (cert->isCA) { der->caSz = SetCa(der->ca, sizeof(der->ca)); if (der->caSz <= 0) return CA_TRUE_E; @@ -26082,8 +26120,21 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, /* set the extensions */ der->extensionsSz = 0; + /* RFC 5280 : 4.2.1.9. Basic Constraints + * The pathLenConstraint field is meaningful only if the cA boolean is + * asserted and the key usage extension, if present, asserts the + * keyCertSign bit */ + /* Set CA and path length */ + if ((cert->isCA) && (cert->pathLen) && + ((cert->keyUsage & KEYUSE_KEY_CERT_SIGN) || (!cert->keyUsage))) { + der->caSz = SetCaWithPathLen(der->ca, sizeof(der->ca), cert->pathLen); + if (der->caSz <= 0) + return CA_TRUE_E; + + der->extensionsSz += der->caSz; + } /* Set CA */ - if (cert->isCA) { + else if (cert->isCA) { der->caSz = SetCa(der->ca, sizeof(der->ca)); if (der->caSz <= 0) return CA_TRUE_E; diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index f9351a765..5f10a0943 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -384,6 +384,8 @@ typedef struct Cert { int selfSigned; /* self signed flag */ CertName subject; /* subject info */ int isCA; /* is this going to be a CA */ + char pathLen; /* max depth of valid certification + * paths that include this cert */ /* internal use only */ int bodySz; /* pre sign total size */ int keyType; /* public key type of subject */ From 1b6ce6150efdde3c247003da43407f8e4ff474f3 Mon Sep 17 00:00:00 2001 From: Stanislav Klima Date: Wed, 13 Jul 2022 09:07:02 +0200 Subject: [PATCH 2/6] unsigned pathlen --- wolfcrypt/src/asn.c | 8 ++++---- wolfssl/wolfcrypt/asn_public.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 1b94cfd44..01ca42362 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -22751,10 +22751,10 @@ static int SetExtensionsHeader(byte* out, word32 outSz, int extSz) /* encode CA basic constraints true with path length * return total bytes written */ -static int SetCaWithPathLen(byte* out, word32 outSz, char pathLen) +static int SetCaWithPathLen(byte* out, word32 outSz, byte pathLen) { /* ASN1->DER sequence for Basic Constraints True and path length */ - byte caPathLenBasicConstASN1[] = { + const byte caPathLenBasicConstASN1[] = { 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00 @@ -22766,10 +22766,10 @@ static int SetCaWithPathLen(byte* out, word32 outSz, char pathLen) if (outSz < sizeof(caPathLenBasicConstASN1)) return BUFFER_E; - caPathLenBasicConstASN1[16U] = pathLen; - XMEMCPY(out, caPathLenBasicConstASN1, sizeof(caPathLenBasicConstASN1)); + out[sizeof(caPathLenBasicConstASN1)-1] = pathLen; + return (int)sizeof(caPathLenBasicConstASN1); } diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 5f10a0943..d350b9aa6 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -384,7 +384,7 @@ typedef struct Cert { int selfSigned; /* self signed flag */ CertName subject; /* subject info */ int isCA; /* is this going to be a CA */ - char pathLen; /* max depth of valid certification + byte pathLen; /* max depth of valid certification * paths that include this cert */ /* internal use only */ int bodySz; /* pre sign total size */ From 6ce5f645f3830dc35d31db6286db70ef3d8fbf0a Mon Sep 17 00:00:00 2001 From: Stanislav Klima Date: Tue, 19 Jul 2022 10:38:47 +0200 Subject: [PATCH 3/6] added ASN template code and WOLFSSL_CERT_EXT, still missing testcase --- wolfcrypt/src/asn.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 01ca42362..396fc821a 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -24344,8 +24344,17 @@ static int EncodeExtensions(Cert* cert, byte* output, word32 maxSz, /* Set Basic Constraints to be a Certificate Authority. */ SetASN_Boolean(&dataASN[CERTEXTSASN_IDX_BC_CA], 1); SetASN_Buffer(&dataASN[CERTEXTSASN_IDX_BC_OID], bcOID, sizeof(bcOID)); - /* TODO: consider adding path length field in Cert. */ - dataASN[CERTEXTSASN_IDX_BC_PATHLEN].noOut = 1; + if (cert->pathLen + #ifdef WOLFSSL_CERT_EXT + && ((cert->keyUsage & KEYUSE_KEY_CERT_SIGN) || (!cert->keyUsage)) + #endif + ) { + SetASN_Int8Bit(&dataASN[CERTEXTSASN_IDX_BC_PATHLEN], + cert->pathLen); + } + else { + dataASN[CERTEXTSASN_IDX_BC_PATHLEN].noOut = 1; + } } else if (cert->basicConstSet) { /* Set Basic Constraints to be a non Certificate Authority. */ @@ -24941,8 +24950,11 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, * asserted and the key usage extension, if present, asserts the * keyCertSign bit */ /* Set CA and path length */ - if ((cert->isCA) && (cert->pathLen) && - ((cert->keyUsage & KEYUSE_KEY_CERT_SIGN) || (!cert->keyUsage))) { + if ((cert->isCA) && (cert->pathLen) +#ifdef WOLFSSL_CERT_EXT + && ((cert->keyUsage & KEYUSE_KEY_CERT_SIGN) || (!cert->keyUsage)) +#endif + ) { der->caSz = SetCaWithPathLen(der->ca, sizeof(der->ca), cert->pathLen); if (der->caSz <= 0) return CA_TRUE_E; From 3d721bd5337e4265327e9c43f06b06717b7b35ea Mon Sep 17 00:00:00 2001 From: Stanislav Klima Date: Tue, 19 Jul 2022 11:00:36 +0200 Subject: [PATCH 4/6] more WOLFSSL_CERT_EXT --- wolfcrypt/src/asn.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 396fc821a..d16df3f12 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -26137,8 +26137,11 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, * asserted and the key usage extension, if present, asserts the * keyCertSign bit */ /* Set CA and path length */ - if ((cert->isCA) && (cert->pathLen) && - ((cert->keyUsage & KEYUSE_KEY_CERT_SIGN) || (!cert->keyUsage))) { + if ((cert->isCA) && (cert->pathLen) +#ifdef WOLFSSL_CERT_EXT + && ((cert->keyUsage & KEYUSE_KEY_CERT_SIGN) || (!cert->keyUsage)) +#endif + ) { der->caSz = SetCaWithPathLen(der->ca, sizeof(der->ca), cert->pathLen); if (der->caSz <= 0) return CA_TRUE_E; From 1a44bad8cc00cabbcf53e9113f22b63a4f14b375 Mon Sep 17 00:00:00 2001 From: Stanislav Klima Date: Tue, 19 Jul 2022 15:34:20 +0200 Subject: [PATCH 5/6] drafted test case for path len --- tests/api.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tests/api.c b/tests/api.c index a19bcf2b1..6dbc055ce 100644 --- a/tests/api.c +++ b/tests/api.c @@ -47071,6 +47071,59 @@ static void test_wc_ParseCert(void) #endif } +static void test_MakeCertWithPathLen(void) +{ +#if defined(WOLFSSL_CERT_REQ) && defined(WOLFSSL_CERT_GEN) && \ + defined(WOLFSSL_KEY_GEN) && defined(HAVE_ECC) + const byte expectedPathLen = 7; + Cert cert; + DecodedCert decodedCert; + byte der[FOURK_BUF]; + int derSize = 0; + WC_RNG rng; + ecc_key key; + + printf(testingFmt, "test_MakeCertWithPathLen"); + + AssertIntEQ(wc_InitRng(&rng), 0); + AssertIntEQ(wc_ecc_init(&key), 0); + AssertIntEQ(wc_ecc_make_key(&rng, 32, &key), 0); + AssertIntEQ(wc_InitCert(&cert), 0); + + (void)strncpy(cert.subject.country, "US", CTC_NAME_SIZE); + (void)strncpy(cert.subject.state, "state", CTC_NAME_SIZE); + (void)strncpy(cert.subject.locality, "Bozeman", CTC_NAME_SIZE); + (void)strncpy(cert.subject.org, "yourOrgNameHere", CTC_NAME_SIZE); + (void)strncpy(cert.subject.unit, "yourUnitNameHere", CTC_NAME_SIZE); + (void)strncpy(cert.subject.commonName, "www.yourDomain.com", CTC_NAME_SIZE); + (void)strncpy(cert.subject.email, "yourEmail@yourDomain.com", CTC_NAME_SIZE); + + cert.selfSigned = 1; + cert.isCA = 1; + cert.pathLen = expectedPathLen; + cert.sigType = CTC_SHA256wECDSA; + +#ifdef WOLFSSL_CERT_EXT + cert.keyUsage |= KEYUSE_KEY_CERT_SIGN; +#endif + + AssertIntGE(wc_MakeCert(&cert, der, FOURK_BUF, NULL, &key, &rng), 0); + derSize = wc_SignCert(cert.bodySz, cert.sigType, der, FOURK_BUF, NULL, + &key, &rng); + AssertIntGE(derSize, 0); + + wc_InitDecodedCert(&decodedCert, der, derSize, NULL); + AssertIntEQ(wc_ParseCert(&decodedCert, CERT_TYPE, NO_VERIFY, NULL), 0); + AssertIntEQ(decodedCert.pathLength, expectedPathLen); + + wc_FreeDecodedCert(&decodedCert); + AssertIntEQ(wc_ecc_free(&key), 0); + AssertIntEQ(wc_FreeRng(&rng), 0); + + printf(resultFmt, passed); +#endif +} + /*----------------------------------------------------------------------------* | wolfCrypt ECC *----------------------------------------------------------------------------*/ @@ -56063,6 +56116,7 @@ void ApiTest(void) test_wc_SetSubject(); test_CheckCertSignature(); test_wc_ParseCert(); + test_MakeCertWithPathLen(); /* wolfCrypt ECC tests */ test_wc_ecc_get_curve_size_from_name(); From 66c5a947fd74203c26fd5464ac03c103ffeaba75 Mon Sep 17 00:00:00 2001 From: Stanislav Klima Date: Wed, 20 Jul 2022 08:56:59 +0200 Subject: [PATCH 6/6] XSTRNCPY, fixed typos --- tests/api.c | 17 ++++++++--------- wolfcrypt/src/asn.c | 4 ++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/tests/api.c b/tests/api.c index 6dbc055ce..38daa8123 100644 --- a/tests/api.c +++ b/tests/api.c @@ -47073,8 +47073,7 @@ static void test_wc_ParseCert(void) static void test_MakeCertWithPathLen(void) { -#if defined(WOLFSSL_CERT_REQ) && defined(WOLFSSL_CERT_GEN) && \ - defined(WOLFSSL_KEY_GEN) && defined(HAVE_ECC) +#if defined(WOLFSSL_CERT_REQ) && defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) const byte expectedPathLen = 7; Cert cert; DecodedCert decodedCert; @@ -47090,13 +47089,13 @@ static void test_MakeCertWithPathLen(void) AssertIntEQ(wc_ecc_make_key(&rng, 32, &key), 0); AssertIntEQ(wc_InitCert(&cert), 0); - (void)strncpy(cert.subject.country, "US", CTC_NAME_SIZE); - (void)strncpy(cert.subject.state, "state", CTC_NAME_SIZE); - (void)strncpy(cert.subject.locality, "Bozeman", CTC_NAME_SIZE); - (void)strncpy(cert.subject.org, "yourOrgNameHere", CTC_NAME_SIZE); - (void)strncpy(cert.subject.unit, "yourUnitNameHere", CTC_NAME_SIZE); - (void)strncpy(cert.subject.commonName, "www.yourDomain.com", CTC_NAME_SIZE); - (void)strncpy(cert.subject.email, "yourEmail@yourDomain.com", CTC_NAME_SIZE); + (void)XSTRNCPY(cert.subject.country, "US", CTC_NAME_SIZE); + (void)XSTRNCPY(cert.subject.state, "state", CTC_NAME_SIZE); + (void)XSTRNCPY(cert.subject.locality, "Bozeman", CTC_NAME_SIZE); + (void)XSTRNCPY(cert.subject.org, "yourOrgNameHere", CTC_NAME_SIZE); + (void)XSTRNCPY(cert.subject.unit, "yourUnitNameHere", CTC_NAME_SIZE); + (void)XSTRNCPY(cert.subject.commonName, "www.yourDomain.com", CTC_NAME_SIZE); + (void)XSTRNCPY(cert.subject.email, "yourEmail@yourDomain.com", CTC_NAME_SIZE); cert.selfSigned = 1; cert.isCA = 1; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index d16df3f12..53807c70b 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -24946,7 +24946,7 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, der->extensionsSz = 0; /* RFC 5280 : 4.2.1.9. Basic Constraints - * The pathLenConstraint field is meaningful only if the cA boolean is + * The pathLenConstraint field is meaningful only if the CA boolean is * asserted and the key usage extension, if present, asserts the * keyCertSign bit */ /* Set CA and path length */ @@ -26133,7 +26133,7 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, der->extensionsSz = 0; /* RFC 5280 : 4.2.1.9. Basic Constraints - * The pathLenConstraint field is meaningful only if the cA boolean is + * The pathLenConstraint field is meaningful only if the CA boolean is * asserted and the key usage extension, if present, asserts the * keyCertSign bit */ /* Set CA and path length */