Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 37 additions & 16 deletions src/x509.c
Original file line number Diff line number Diff line change
Expand Up @@ -686,17 +686,24 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc)
/* extCount == loc. Now get the extension. */
/* Check if extension has been set */
isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509, nid);
ext->obj = wolfSSL_OBJ_nid2obj(nid);
if (ext->obj == NULL) {
WOLFSSL_MSG("\tfail: Invalid OBJECT");
wolfSSL_X509_EXTENSION_free(ext);
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
#endif
return NULL;

if (wolfSSL_OBJ_nid2ln(nid) != NULL) {
/* This is NOT an unknown OID. */
ext->obj = wolfSSL_OBJ_nid2obj(nid);
if (ext->obj == NULL) {
WOLFSSL_MSG("\tfail: Invalid OBJECT");
wolfSSL_X509_EXTENSION_free(ext);
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
#endif
return NULL;
}
}

if (ext->obj) {
ext->obj->nid = nid;
}
ext->obj->nid = nid;

switch (oid) {
case BASIC_CA_OID:
Expand Down Expand Up @@ -1000,8 +1007,8 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc)
default:
WOLFSSL_MSG("Unknown extension type found, parsing OID");
/* If the extension type is not recognized/supported,
set the ASN1_OBJECT in the extension with the
parsed oid for access in later function calls */
* set the ASN1_OBJECT in the extension with the
* parsed oid for access in later function calls */

/* Get OID from input */
if (GetASNObjectId(input, &idx, &length, sz) != 0) {
Expand Down Expand Up @@ -1030,6 +1037,18 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc)
objSz += length;

/* Set object size and reallocate space in object buffer */
if (ext->obj == NULL) {
ext->obj = wolfSSL_ASN1_OBJECT_new();
if (ext->obj == NULL) {
wolfSSL_X509_EXTENSION_free(ext);
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
XFREE(cert, NULL, DYNAMIC_TYPE_DCERT);
#endif
return NULL;
}
}

ext->obj->objSz = objSz;
if(((ext->obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) ||
(ext->obj->obj == NULL)) {
Expand Down Expand Up @@ -4600,10 +4619,12 @@ static void wolfSSL_GENERAL_NAME_type_free(WOLFSSL_GENERAL_NAME* name)
name->d.registeredID = NULL;
break;
case GEN_OTHERNAME:
wolfSSL_ASN1_OBJECT_free(name->d.otherName->type_id);
wolfSSL_ASN1_TYPE_free(name->d.otherName->value);
XFREE(name->d.otherName, NULL, DYNAMIC_TYPE_ASN1);
name->d.otherName = NULL;
if (name->d.otherName != NULL) {
wolfSSL_ASN1_OBJECT_free(name->d.otherName->type_id);
wolfSSL_ASN1_TYPE_free(name->d.otherName->value);
XFREE(name->d.otherName, NULL, DYNAMIC_TYPE_ASN1);
name->d.otherName = NULL;
}
break;
case GEN_X400:
/* Unsupported: fall through */
Expand Down
104 changes: 102 additions & 2 deletions tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -43869,7 +43869,13 @@ static int test_GENERAL_NAME_set0_othername(void) {
#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && \
defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_ALT_NAMES) && \
defined(WOLFSSL_CERT_EXT) && !defined(NO_FILESYSTEM)
defined(WOLFSSL_CERT_EXT) && !defined(NO_FILESYSTEM) && \
defined(WOLFSSL_FPKI)

/* ./configure --enable-opensslall --enable-certgen --enable-certreq
* --enable-certext --enable-debug 'CPPFLAGS=-DWOLFSSL_CUSTOM_OID
* -DWOLFSSL_ALT_NAMES -DWOLFSSL_FPKI' */

const char * cert_fname = "./certs/server-cert.der";
const char * key_fname = "./certs/server-key.der";
X509* x509 = NULL;
Expand All @@ -43885,6 +43891,18 @@ static int test_GENERAL_NAME_set0_othername(void) {
int derSz = 0;
EVP_PKEY* priv = NULL;
FILE* f = NULL;
/* The length of this buffer is 37 */
const unsigned char expected_asn1[] = {
/* OID specifier and length */
0x06, 0x0A,
/* 1.3.6.1.4.1.311.20.2.3 */
0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x03,
/* TODO */
0xA0, 0x17, 0x0C, 0x15,
/* othername@wolfssl.com */
0x6F, 0x74, 0x68, 0x65, 0x72, 0x6E, 0x61, 0x6D, 0x65, 0x40, 0x77, 0x6F,
0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D
};

AssertNotNull(f = fopen(cert_fname, "rb"));
AssertNotNull(x509 = d2i_X509_fp(f, NULL));
Expand All @@ -43908,6 +43926,25 @@ static int test_GENERAL_NAME_set0_othername(void) {
(const unsigned char**)&pt, derSz));
AssertIntGT(X509_sign(x509, priv, EVP_sha256()), 0);
sk_GENERAL_NAME_pop_free(gns, GENERAL_NAME_free);
AssertNotNull(gns = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL,
NULL));

AssertIntEQ(sk_GENERAL_NAME_num(gns), 3);

AssertNotNull(gn = sk_GENERAL_NAME_value(gns, 2));
AssertIntEQ(gn->type, 0);

/* It is odd that we are using ASN_RFC822_TYPE. It is because when we are
* parsing der, the string is not fully parsed. It is still raw der whereas
* when we encode we set the oid (for example, upn) and value. As we are
* overloading the meaning of the type, here we manually do the right thing.
*/
AssertIntEQ(ASN1_STRING_length(gn->d.rfc822Name), 37);
AssertIntEQ(XMEMCMP(ASN1_STRING_data(gn->d.rfc822Name), expected_asn1, 37),
0);
gn->type = ASN_RFC822_TYPE;
sk_GENERAL_NAME_pop_free(gns, GENERAL_NAME_free);

ASN1_OBJECT_free(upn_oid);
X509_EXTENSION_free(ext);
X509_free(x509);
Expand All @@ -43923,7 +43960,13 @@ static int test_othername_and_SID_ext(void) {
#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && \
defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_ALT_NAMES) && \
defined(WOLFSSL_CERT_EXT) && !defined(NO_FILESYSTEM)
defined(WOLFSSL_CERT_EXT) && !defined(NO_FILESYSTEM) && \
defined(WOLFSSL_FPKI) && defined(WOLFSSL_ASN_TEMPLATE)

/* ./configure --enable-opensslall --enable-certgen --enable-certreq
* --enable-certext --enable-debug 'CPPFLAGS=-DWOLFSSL_CUSTOM_OID
* -DWOLFSSL_ALT_NAMES -DWOLFSSL_FPKI' */


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

X509_EXTENSION * san_ext = NULL;
X509_EXTENSION * ext = NULL;
GENERAL_NAME* gn = NULL;
GENERAL_NAMES* gns = NULL;
ASN1_OBJECT* upn_oid = NULL;
ASN1_UTF8STRING *utf8str = NULL;
ASN1_TYPE *value = NULL;
ASN1_STRING *extval = NULL;

/* SID extension. SID data format explained here:
* https://blog.qdsecurity.se/2022/05/27/manually-injecting-a-sid-in-a-certificate/
Expand All @@ -43948,13 +43993,21 @@ static int test_othername_and_SID_ext(void) {
48, 4, 46, 83, 45, 49, 45, 53, 45, 50, 49, 45, 50, 56, 52, 51, 57,
48, 55, 52, 49, 56, 45, 51, 57, 50, 54, 50, 55, 55, 52, 50, 49, 45,
51, 56, 49, 53, 57, 57, 51, 57, 55, 50, 45, 52, 54, 48, 49};

uint8_t expectedAltName[] = {
0x30, 0x27, 0xA0, 0x25, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82,
0x37, 0x14, 0x02, 0x03, 0xA0, 0x17, 0x0C, 0x15, 0x6F, 0x74, 0x68, 0x65,
0x72, 0x6E, 0x61, 0x6D, 0x65, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73,
0x6C, 0x2E, 0x63, 0x6F, 0x6D};

X509_EXTENSION *sid_ext = NULL;
ASN1_OBJECT* sid_oid = NULL;
ASN1_OCTET_STRING *sid_data = NULL;

EVP_PKEY* priv = NULL;
FILE* f = NULL;
byte* pt = NULL;
BIO* bio = NULL;

AssertNotNull(f = fopen(csr_fname, "rb"));
AssertNotNull(x509 = d2i_X509_REQ_fp(f, NULL));
Expand Down Expand Up @@ -43996,7 +44049,54 @@ static int test_othername_and_SID_ext(void) {
ASN1_OBJECT_free(sid_oid);
ASN1_OCTET_STRING_free(sid_data);
X509_REQ_free(x509);
x509 = NULL;
EVP_PKEY_free(priv);

/* At this point everything used to generate what is in der is cleaned up.
* We now read back from der to confirm the extensions were inserted
* correctly. */
bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
AssertNotNull(bio);

AssertIntEQ(BIO_write(bio, der, derSz), derSz); /* d2i consumes BIO */
d2i_X509_REQ_bio(bio, &x509);
AssertNotNull(x509);
BIO_free(bio);
AssertNotNull(exts = (STACK_OF(X509_EXTENSION)*) X509_REQ_get_extensions(
x509));
AssertIntEQ(sk_X509_EXTENSION_num(exts), 2);

/* Check the SID extension. */
AssertNotNull(ext = sk_X509_EXTENSION_value(exts, 0));
AssertNotNull(extval = X509_EXTENSION_get_data(ext));
AssertIntEQ(extval->length, sizeof(SidExtension));
AssertIntEQ(XMEMCMP(SidExtension, extval->data, sizeof(SidExtension)), 0);

/* Check the AltNames extension. */
AssertNotNull(ext = sk_X509_EXTENSION_value(exts, 1));
AssertNotNull(extval = X509_EXTENSION_get_data(ext));
AssertIntEQ(extval->length, sizeof(expectedAltName));
AssertIntEQ(XMEMCMP(expectedAltName, extval->data, sizeof(expectedAltName)),
0);

/* Cleanup */
AssertNotNull(gns = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL,
NULL));
AssertIntEQ(sk_GENERAL_NAME_num(gns), 1);
AssertNotNull(gn = sk_GENERAL_NAME_value(gns, 0));
AssertIntEQ(gn->type, 0);

/* It is odd that we are using ASN_RFC822_TYPE. It is because when we are
* parsing der, the string is not fully parsed. It is still raw der whereas
* when we encode we set the oid (for example, upn) and value. As we are
* overloading the meaning of the type, here we manually do the right thing.
*/
gn->type = ASN_RFC822_TYPE;
sk_GENERAL_NAME_pop_free(gns, GENERAL_NAME_free);

ext->ext_sk->data.gn->type = ASN_RFC822_TYPE;
sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
X509_REQ_free(x509);
res = TEST_RES_CHECK(1);
#endif
return res;
Expand Down