Skip to content

Commit 0ebe581

Browse files
committed
Allow for unknown OIDs in extensions in wolfSSL_X509_set_ext()
...and add some testing to show we properly inserted the extensions.
1 parent bdd4535 commit 0ebe581

2 files changed

Lines changed: 124 additions & 17 deletions

File tree

src/x509.c

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -687,16 +687,9 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc)
687687
/* Check if extension has been set */
688688
isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509, nid);
689689
ext->obj = wolfSSL_OBJ_nid2obj(nid);
690-
if (ext->obj == NULL) {
691-
WOLFSSL_MSG("\tfail: Invalid OBJECT");
692-
wolfSSL_X509_EXTENSION_free(ext);
693-
FreeDecodedCert(cert);
694-
#ifdef WOLFSSL_SMALL_STACK
695-
XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
696-
#endif
697-
return NULL;
690+
if (ext->obj != NULL) {
691+
ext->obj->nid = nid;
698692
}
699-
ext->obj->nid = nid;
700693

701694
switch (oid) {
702695
case BASIC_CA_OID:
@@ -1000,8 +993,8 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc)
1000993
default:
1001994
WOLFSSL_MSG("Unknown extension type found, parsing OID");
1002995
/* If the extension type is not recognized/supported,
1003-
set the ASN1_OBJECT in the extension with the
1004-
parsed oid for access in later function calls */
996+
* set the ASN1_OBJECT in the extension with the
997+
* parsed oid for access in later function calls */
1005998

1006999
/* Get OID from input */
10071000
if (GetASNObjectId(input, &idx, &length, sz) != 0) {
@@ -1030,6 +1023,18 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc)
10301023
objSz += length;
10311024

10321025
/* Set object size and reallocate space in object buffer */
1026+
if (ext->obj == NULL) {
1027+
ext->obj = wolfSSL_ASN1_OBJECT_new();
1028+
if (ext->obj == NULL) {
1029+
wolfSSL_X509_EXTENSION_free(ext);
1030+
FreeDecodedCert(cert);
1031+
#ifdef WOLFSSL_SMALL_STACK
1032+
XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
1033+
#endif
1034+
return NULL;
1035+
}
1036+
}
1037+
10331038
ext->obj->objSz = objSz;
10341039
if(((ext->obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) ||
10351040
(ext->obj->obj == NULL)) {
@@ -4600,10 +4605,12 @@ static void wolfSSL_GENERAL_NAME_type_free(WOLFSSL_GENERAL_NAME* name)
46004605
name->d.registeredID = NULL;
46014606
break;
46024607
case GEN_OTHERNAME:
4603-
wolfSSL_ASN1_OBJECT_free(name->d.otherName->type_id);
4604-
wolfSSL_ASN1_TYPE_free(name->d.otherName->value);
4605-
XFREE(name->d.otherName, NULL, DYNAMIC_TYPE_ASN1);
4606-
name->d.otherName = NULL;
4608+
if (name->d.otherName != NULL) {
4609+
wolfSSL_ASN1_OBJECT_free(name->d.otherName->type_id);
4610+
wolfSSL_ASN1_TYPE_free(name->d.otherName->value);
4611+
XFREE(name->d.otherName, NULL, DYNAMIC_TYPE_ASN1);
4612+
name->d.otherName = NULL;
4613+
}
46074614
break;
46084615
case GEN_X400:
46094616
/* Unsupported: fall through */

tests/api.c

Lines changed: 102 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43869,7 +43869,13 @@ static int test_GENERAL_NAME_set0_othername(void) {
4386943869
#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \
4387043870
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && \
4387143871
defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_ALT_NAMES) && \
43872-
defined(WOLFSSL_CERT_EXT) && !defined(NO_FILESYSTEM)
43872+
defined(WOLFSSL_CERT_EXT) && !defined(NO_FILESYSTEM) && \
43873+
defined(WOLFSSL_FPKI)
43874+
43875+
/* ./configure --enable-opensslall --enable-certgen --enable-certreq
43876+
* --enable-certext --enable-debug 'CPPFLAGS=-DWOLFSSL_CUSTOM_OID
43877+
* -DWOLFSSL_ALT_NAMES -DWOLFSSL_FPKI' */
43878+
4387343879
const char * cert_fname = "./certs/server-cert.der";
4387443880
const char * key_fname = "./certs/server-key.der";
4387543881
X509* x509 = NULL;
@@ -43885,6 +43891,18 @@ static int test_GENERAL_NAME_set0_othername(void) {
4388543891
int derSz = 0;
4388643892
EVP_PKEY* priv = NULL;
4388743893
FILE* f = NULL;
43894+
/* The length of this buffer is 37 */
43895+
const unsigned char expected_asn1[] = {
43896+
/* OID specifier and length */
43897+
0x06, 0x0A,
43898+
/* 1.3.6.1.4.1.311.20.2.3 */
43899+
0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x03,
43900+
/* TODO */
43901+
0xA0, 0x17, 0x0C, 0x15,
43902+
/* othername@wolfssl.com */
43903+
0x6F, 0x74, 0x68, 0x65, 0x72, 0x6E, 0x61, 0x6D, 0x65, 0x40, 0x77, 0x6F,
43904+
0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D
43905+
};
4388843906

4388943907
AssertNotNull(f = fopen(cert_fname, "rb"));
4389043908
AssertNotNull(x509 = d2i_X509_fp(f, NULL));
@@ -43908,6 +43926,25 @@ static int test_GENERAL_NAME_set0_othername(void) {
4390843926
(const unsigned char**)&pt, derSz));
4390943927
AssertIntGT(X509_sign(x509, priv, EVP_sha256()), 0);
4391043928
sk_GENERAL_NAME_pop_free(gns, GENERAL_NAME_free);
43929+
AssertNotNull(gns = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL,
43930+
NULL));
43931+
43932+
AssertIntEQ(sk_GENERAL_NAME_num(gns), 3);
43933+
43934+
AssertNotNull(gn = sk_GENERAL_NAME_value(gns, 2));
43935+
AssertIntEQ(gn->type, 0);
43936+
43937+
/* It is odd that we are using ASN_RFC822_TYPE. It is because when we are
43938+
* parsing der, the string is not fully parsed. It is still raw der whereas
43939+
* when we encode we set the oid (for example, upn) and value. As we are
43940+
* overloading the meaning of the type, here we manually do the right thing.
43941+
*/
43942+
AssertIntEQ(ASN1_STRING_length(gn->d.rfc822Name), 37);
43943+
AssertIntEQ(XMEMCMP(ASN1_STRING_data(gn->d.rfc822Name), expected_asn1, 37),
43944+
0);
43945+
gn->type = ASN_RFC822_TYPE;
43946+
sk_GENERAL_NAME_pop_free(gns, GENERAL_NAME_free);
43947+
4391143948
ASN1_OBJECT_free(upn_oid);
4391243949
X509_EXTENSION_free(ext);
4391343950
X509_free(x509);
@@ -43923,7 +43960,13 @@ static int test_othername_and_SID_ext(void) {
4392343960
#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \
4392443961
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && \
4392543962
defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_ALT_NAMES) && \
43926-
defined(WOLFSSL_CERT_EXT) && !defined(NO_FILESYSTEM)
43963+
defined(WOLFSSL_CERT_EXT) && !defined(NO_FILESYSTEM) && \
43964+
defined(WOLFSSL_FPKI) && defined(WOLFSSL_ASN_TEMPLATE)
43965+
43966+
/* ./configure --enable-opensslall --enable-certgen --enable-certreq
43967+
* --enable-certext --enable-debug 'CPPFLAGS=-DWOLFSSL_CUSTOM_OID
43968+
* -DWOLFSSL_ALT_NAMES -DWOLFSSL_FPKI' */
43969+
4392743970

4392843971
const char* csr_fname = "./certs/csr.signed.der";
4392943972
const char* key_fname = "./certs/server-key.der";
@@ -43934,11 +43977,13 @@ static int test_othername_and_SID_ext(void) {
4393443977
STACK_OF(X509_EXTENSION) *exts = NULL;
4393543978

4393643979
X509_EXTENSION * san_ext = NULL;
43980+
X509_EXTENSION * ext = NULL;
4393743981
GENERAL_NAME* gn = NULL;
4393843982
GENERAL_NAMES* gns = NULL;
4393943983
ASN1_OBJECT* upn_oid = NULL;
4394043984
ASN1_UTF8STRING *utf8str = NULL;
4394143985
ASN1_TYPE *value = NULL;
43986+
ASN1_STRING *extval = NULL;
4394243987

4394343988
/* SID extension. SID data format explained here:
4394443989
* https://blog.qdsecurity.se/2022/05/27/manually-injecting-a-sid-in-a-certificate/
@@ -43948,13 +43993,21 @@ static int test_othername_and_SID_ext(void) {
4394843993
48, 4, 46, 83, 45, 49, 45, 53, 45, 50, 49, 45, 50, 56, 52, 51, 57,
4394943994
48, 55, 52, 49, 56, 45, 51, 57, 50, 54, 50, 55, 55, 52, 50, 49, 45,
4395043995
51, 56, 49, 53, 57, 57, 51, 57, 55, 50, 45, 52, 54, 48, 49};
43996+
43997+
uint8_t expectedAltName[] = {
43998+
0x30, 0x27, 0xA0, 0x25, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82,
43999+
0x37, 0x14, 0x02, 0x03, 0xA0, 0x17, 0x0C, 0x15, 0x6F, 0x74, 0x68, 0x65,
44000+
0x72, 0x6E, 0x61, 0x6D, 0x65, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73,
44001+
0x6C, 0x2E, 0x63, 0x6F, 0x6D};
44002+
4395144003
X509_EXTENSION *sid_ext = NULL;
4395244004
ASN1_OBJECT* sid_oid = NULL;
4395344005
ASN1_OCTET_STRING *sid_data = NULL;
4395444006

4395544007
EVP_PKEY* priv = NULL;
4395644008
FILE* f = NULL;
4395744009
byte* pt = NULL;
44010+
BIO* bio = NULL;
4395844011

4395944012
AssertNotNull(f = fopen(csr_fname, "rb"));
4396044013
AssertNotNull(x509 = d2i_X509_REQ_fp(f, NULL));
@@ -43996,7 +44049,54 @@ static int test_othername_and_SID_ext(void) {
4399644049
ASN1_OBJECT_free(sid_oid);
4399744050
ASN1_OCTET_STRING_free(sid_data);
4399844051
X509_REQ_free(x509);
44052+
x509 = NULL;
4399944053
EVP_PKEY_free(priv);
44054+
44055+
/* At this point everything used to generate what is in der is cleaned up.
44056+
* We now read back from der to confirm the extensions were inserted
44057+
* correctly. */
44058+
bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
44059+
AssertNotNull(bio);
44060+
44061+
AssertIntEQ(BIO_write(bio, der, derSz), derSz); /* d2i consumes BIO */
44062+
d2i_X509_REQ_bio(bio, &x509);
44063+
AssertNotNull(x509);
44064+
BIO_free(bio);
44065+
AssertNotNull(exts = (STACK_OF(X509_EXTENSION)*) X509_REQ_get_extensions(
44066+
x509));
44067+
AssertIntEQ(sk_X509_EXTENSION_num(exts), 2);
44068+
44069+
/* Check the SID extension. */
44070+
AssertNotNull(ext = sk_X509_EXTENSION_value(exts, 0));
44071+
AssertNotNull(extval = X509_EXTENSION_get_data(ext));
44072+
AssertIntEQ(extval->length, sizeof(SidExtension));
44073+
AssertIntEQ(XMEMCMP(SidExtension, extval->data, sizeof(SidExtension)), 0);
44074+
44075+
/* Check the AltNames extension. */
44076+
AssertNotNull(ext = sk_X509_EXTENSION_value(exts, 1));
44077+
AssertNotNull(extval = X509_EXTENSION_get_data(ext));
44078+
AssertIntEQ(extval->length, sizeof(expectedAltName));
44079+
AssertIntEQ(XMEMCMP(expectedAltName, extval->data, sizeof(expectedAltName)),
44080+
0);
44081+
44082+
/* Cleanup */
44083+
AssertNotNull(gns = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL,
44084+
NULL));
44085+
AssertIntEQ(sk_GENERAL_NAME_num(gns), 1);
44086+
AssertNotNull(gn = sk_GENERAL_NAME_value(gns, 0));
44087+
AssertIntEQ(gn->type, 0);
44088+
44089+
/* It is odd that we are using ASN_RFC822_TYPE. It is because when we are
44090+
* parsing der, the string is not fully parsed. It is still raw der whereas
44091+
* when we encode we set the oid (for example, upn) and value. As we are
44092+
* overloading the meaning of the type, here we manually do the right thing.
44093+
*/
44094+
gn->type = ASN_RFC822_TYPE;
44095+
sk_GENERAL_NAME_pop_free(gns, GENERAL_NAME_free);
44096+
44097+
ext->ext_sk->data.gn->type = ASN_RFC822_TYPE;
44098+
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
44099+
X509_REQ_free(x509);
4400044100
res = TEST_RES_CHECK(1);
4400144101
#endif
4400244102
return res;

0 commit comments

Comments
 (0)