Browse Source

Support in the compatibility layer for UPN and SID.

Anthony Hu 1 year ago
parent
commit
120d1f0d1a
11 changed files with 530 additions and 46 deletions
  1. 13 1
      src/internal.c
  2. 280 20
      src/x509.c
  3. 142 1
      tests/api.c
  4. 44 1
      wolfcrypt/src/asn.c
  5. 4 0
      wolfssl/internal.h
  6. 2 0
      wolfssl/openssl/asn1.h
  7. 20 11
      wolfssl/openssl/ssl.h
  8. 1 0
      wolfssl/openssl/x509v3.h
  9. 11 0
      wolfssl/ssl.h
  10. 3 0
      wolfssl/wolfcrypt/asn.h
  11. 10 12
      wolfssl/wolfcrypt/asn_public.h

+ 13 - 1
src/internal.c

@@ -4238,6 +4238,10 @@ void InitX509(WOLFSSL_X509* x509, int dynamicFlag, void* heap)
 /* Free wolfSSL X509 type */
 void FreeX509(WOLFSSL_X509* x509)
 {
+    #if defined(WOLFSSL_CERT_REQ) && defined(OPENSSL_ALL) \
+    &&  defined( WOLFSSL_CUSTOM_OID)
+    int idx;
+    #endif /* WOLFSSL_CERT_REQ && OPENSSL_ALL && WOLFSSL_CUSTOM_OID */
     if (x509 == NULL)
         return;
 
@@ -4318,7 +4322,15 @@ void FreeX509(WOLFSSL_X509* x509)
         if (x509->reqAttributes) {
             wolfSSL_sk_pop_free(x509->reqAttributes, NULL);
         }
-    #endif /* WOLFSSL_CERT_REQ */
+    #ifdef WOLFSSL_CUSTOM_OID
+        for (idx = 0; idx < x509->customExtCount; idx++) {
+            XFREE(x509->custom_exts[idx].oid, x509->heap,
+                  DYNAMIC_TYPE_X509_EXT);
+            XFREE(x509->custom_exts[idx].val, x509->heap,
+                  DYNAMIC_TYPE_X509_EXT);
+        }
+    #endif /* WOLFSSL_CUSTOM_OID */
+    #endif /* WOLFSSL_CERT_REQ && OPENSSL_ALL */
     if (x509->altNames) {
         FreeAltNames(x509->altNames, x509->heap);
         x509->altNames = NULL;

+ 280 - 20
src/x509.c

@@ -282,6 +282,55 @@ WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_dup(WOLFSSL_X509_EXTENSION* src)
     return ret;
 }
 
+WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_create_by_OBJ(
+    WOLFSSL_X509_EXTENSION* ex, WOLFSSL_ASN1_OBJECT *obj, int crit,
+    WOLFSSL_ASN1_STRING *data)
+{
+    int err = 0;
+    WOLFSSL_X509_EXTENSION *ret = ex;
+
+    WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_create_by_OBJ");
+
+    if ((obj == NULL) || (data == NULL)) {
+       return NULL;
+    }
+
+    if (ret == NULL) {
+        ret = wolfSSL_X509_EXTENSION_new();
+        if (ret == NULL) {
+            err = 1;
+        }
+    } else {
+        /* Prevent potential memory leaks and dangling pointers. */
+        wolfSSL_ASN1_OBJECT_free(ret->obj);
+        ret->obj = NULL;
+        wolfSSL_ASN1_STRING_free(&ret->value);
+    }
+
+    ret->crit = crit;
+
+    if (err == 0) {
+        ret->obj = wolfSSL_ASN1_OBJECT_dup(obj);
+        if (ret->obj == NULL) {
+            err = 1;
+        }
+    }
+
+    if (err == 0) {
+        if (wolfSSL_ASN1_STRING_copy(&ret->value, data) != WOLFSSL_SUCCESS) {
+            err = 1;
+        }
+    }
+
+    if (err == 1) {
+        if (ret != ex) {
+            wolfSSL_X509_EXTENSION_free(ret);
+        }
+        ret = NULL;
+    }
+    return ret;
+}
+
 /* Creates and returns a new WOLFSSL_X509_EXTENSION stack. */
 WOLFSSL_STACK* wolfSSL_sk_new_x509_ext(void)
 {
@@ -295,7 +344,9 @@ WOLFSSL_STACK* wolfSSL_sk_new_x509_ext(void)
     return sk;
 }
 
-/* return 1 on success 0 on fail */
+/* This function does NOT return 1 on success. It returns 0 on fail, and the
+ * number of items in the stack upon success. This is for compatibility with
+ * OpenSSL. */
 int wolfSSL_sk_X509_EXTENSION_push(WOLFSSL_STACK* sk,WOLFSSL_X509_EXTENSION* ext)
 {
     WOLFSSL_STACK* node;
@@ -310,7 +361,7 @@ int wolfSSL_sk_X509_EXTENSION_push(WOLFSSL_STACK* sk,WOLFSSL_X509_EXTENSION* ext
     if (sk->data.ext == NULL) {
         sk->data.ext = ext;
         sk->num += 1;
-        return WOLFSSL_SUCCESS;
+        return (int)sk->num;
     }
 
     /* stack already has value(s) create a new node and add more */
@@ -330,7 +381,7 @@ int wolfSSL_sk_X509_EXTENSION_push(WOLFSSL_STACK* sk,WOLFSSL_X509_EXTENSION* ext
     sk->data.ext    = ext;
     sk->num        += 1;
 
-    return WOLFSSL_SUCCESS;
+    return (int)sk->num;
 }
 
 /* Free the structure for X509_EXTENSION stack
@@ -1133,7 +1184,34 @@ int wolfSSL_X509_add_ext(WOLFSSL_X509 *x509, WOLFSSL_X509_EXTENSION *ext, int lo
         WOLFSSL_GENERAL_NAMES* gns = ext->ext_sk;
         while (gns) {
             WOLFSSL_GENERAL_NAME* gn = gns->data.gn;
-            if (!gn || !gn->d.ia5 ||
+            if ((gn != NULL) && (gn->type == ASN_OTHER_TYPE)) {
+                char *buf = NULL;
+                int ret = 0;
+                word32 len = 0;
+
+                len = SetOthername(gn->d.otherName, NULL);
+                if (len == WOLFSSL_FAILURE) {
+                    return WOLFSSL_FAILURE;
+                }
+
+                buf = (char*)XMALLOC(len, x509->heap, DYNAMIC_TYPE_X509_EXT);
+                if (buf == NULL) {
+                    WOLFSSL_MSG("Couldn't allocate memory for othername");
+                    return WOLFSSL_FAILURE;
+                }
+
+                /* SetOthername() cannot fail; already passed above. */
+                SetOthername(gn->d.otherName, (byte*)buf);
+
+                ret = wolfSSL_X509_add_altname_ex(x509, buf, len,
+                                                  ASN_OTHER_TYPE);
+                XFREE(buf, x509->heap, DYNAMIC_TYPE_X509_EXT);
+                if (ret == WOLFSSL_FAILURE) {
+                     WOLFSSL_MSG("wolfSSL_X509_add_altname_ex() failed");
+                     return WOLFSSL_FAILURE;
+                }
+            }
+            else if (!gn || !gn->d.ia5 ||
                 wolfSSL_X509_add_altname_ex(x509, gn->d.ia5->data,
                     gn->d.ia5->length, gn->type) != WOLFSSL_SUCCESS) {
                 WOLFSSL_MSG("Subject alternative name missing extension");
@@ -1163,8 +1241,54 @@ int wolfSSL_X509_add_ext(WOLFSSL_X509 *x509, WOLFSSL_X509_EXTENSION *ext, int lo
         }
         break;
     default:
+#ifdef WOLFSSL_CUSTOM_OID
+        if ((ext->obj == NULL) || (ext->value.length == 0)) {
+            WOLFSSL_MSG("Extension has insufficient information.");
+            return WOLFSSL_FAILURE;
+        }
+
+        if ((x509->customExtCount < 0) ||
+            (x509->customExtCount >= NUM_CUSTOM_EXT)) {
+            WOLFSSL_MSG("Bad value for customExtCount.");
+            return WOLFSSL_FAILURE;
+        }
+
+        /* This is a viable custom extension. */
+        char *oid = XMALLOC(MAX_OID_STRING_SZ, x509->heap,
+                            DYNAMIC_TYPE_X509_EXT);
+        byte *val = XMALLOC(ext->value.length, x509->heap,
+                            DYNAMIC_TYPE_X509_EXT);
+        int err = 0;
+
+        if ((oid == NULL) || (val == NULL)) {
+            WOLFSSL_MSG("Memory allocation failure.\n");
+            err = 1;
+        }
+
+        if (err == 0) {
+            XMEMCPY(val, ext->value.data, ext->value.length);
+            if (wolfSSL_OBJ_obj2txt(oid, MAX_OID_STRING_SZ, ext->obj, 1) < 0) {
+                err = 1;
+            }
+        }
+
+        if (err == 1) {
+            XFREE(val, x509->heap, DYNAMIC_TYPE_X509_EXT);
+            XFREE(oid, x509->heap, DYNAMIC_TYPE_X509_EXT);
+            return WOLFSSL_FAILURE;
+        }
+
+        /* x509->custom_exts now owns the buffers and they must be managed. */
+        x509->custom_exts[x509->customExtCount].oid = oid;
+        x509->custom_exts[x509->customExtCount].crit = ext->crit;
+        x509->custom_exts[x509->customExtCount].val = val;
+        x509->custom_exts[x509->customExtCount].valSz = ext->value.length;
+        x509->customExtCount++;
+#else
         WOLFSSL_MSG("Unsupported extension to add");
         return WOLFSSL_FAILURE;
+#endif /* WOLFSSL_CUSTOM_OID */
+        break;
     }
 
     return WOLFSSL_SUCCESS;
@@ -2697,6 +2821,12 @@ WOLFSSL_X509_EXTENSION *wolfSSL_X509V3_EXT_i2d(int nid, int crit,
             WOLFSSL_MSG("wolfSSL_sk_dup failed");
             goto err_cleanup;
         }
+
+        if (!(ext->obj = wolfSSL_OBJ_nid2obj(nid))) {
+            WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_new failed");
+            goto err_cleanup;
+        }
+
         break;
     }
     case NID_basic_constraints:
@@ -3343,6 +3473,7 @@ WOLFSSL_X509* wolfSSL_X509_REQ_d2i(WOLFSSL_X509** x509,
     return d2i_X509orX509REQ(x509, in, len, 1);
 }
 #endif
+
 #endif /* KEEP_PEER_CERT || SESSION_CERTS || OPENSSL_EXTRA ||
           OPENSSL_EXTRA_X509_SMALL */
 
@@ -4005,6 +4136,7 @@ WOLFSSL_GENERAL_NAME* wolfSSL_GENERAL_NAME_new(void)
         wolfSSL_GENERAL_NAME_free(gn);
         return NULL;
     }
+    gn->type = GEN_IA5;
     return gn;
 }
 
@@ -4024,6 +4156,8 @@ WOLFSSL_GENERAL_NAME* wolfSSL_GENERAL_NAME_dup(WOLFSSL_GENERAL_NAME* gn)
         return NULL;
     }
 
+    wolfSSL_ASN1_STRING_free(dupl->d.ia5);
+    dupl->d.ia5 = NULL;
     switch (gn->type) {
     /* WOLFSSL_ASN1_STRING types */
     case GEN_DNS:
@@ -4052,6 +4186,37 @@ WOLFSSL_GENERAL_NAME* wolfSSL_GENERAL_NAME_dup(WOLFSSL_GENERAL_NAME* gn)
         }
         break;
     case GEN_OTHERNAME:
+        if (gn->d.otherName->value->type != V_ASN1_UTF8STRING) {
+            WOLFSSL_MSG("Unsupported othername value type");
+            goto error;
+        }
+        dupl->d.otherName = (WOLFSSL_ASN1_OTHERNAME*)XMALLOC(
+            sizeof(WOLFSSL_ASN1_OTHERNAME), NULL, DYNAMIC_TYPE_ASN1);
+        if (dupl->d.otherName == NULL) {
+            WOLFSSL_MSG("XMALLOC error");
+            goto error;
+        }
+        dupl->d.otherName->type_id = wolfSSL_ASN1_OBJECT_dup(
+            gn->d.otherName->type_id);
+        dupl->d.otherName->value = (WOLFSSL_ASN1_TYPE*)XMALLOC(
+            sizeof(WOLFSSL_ASN1_TYPE), NULL, DYNAMIC_TYPE_ASN1);
+        if (dupl->d.otherName->value != NULL) {
+            dupl->d.otherName->value->type = gn->d.otherName->value->type;
+            dupl->d.otherName->value->value.utf8string =
+                wolfSSL_ASN1_STRING_dup(
+                                      gn->d.otherName->value->value.utf8string);
+        }
+        if ((dupl->d.otherName->type_id == NULL) ||
+            (dupl->d.otherName->value == NULL) ||
+            (dupl->d.otherName->value->value.utf8string == NULL)) {
+            wolfSSL_ASN1_OBJECT_free(dupl->d.otherName->type_id);
+            wolfSSL_ASN1_TYPE_free(dupl->d.otherName->value);
+            XFREE(dupl->d.otherName, NULL, DYNAMIC_TYPE_ASN1);
+            dupl->d.otherName = NULL;
+            WOLFSSL_MSG("error duping othername");
+            goto error;
+        }
+        break;
     case GEN_X400:
     case GEN_DIRNAME:
     case GEN_EDIPARTY:
@@ -4070,6 +4235,33 @@ error:
     return NULL;
 }
 
+/* Set an Othername in a general name.
+ *
+ * @param [out] gen     Pointer to the GENERAL_NAME where the othername is set.
+ * @param [in]  oid     Object ID (ie UPN).
+ * @param [in]  name    The actual name.
+ * @return  WOLFSSL_FAILURE on invalid parameter or memory error,
+ *          WOLFSSL_SUCCESS otherwise.
+ */
+int wolfSSL_GENERAL_NAME_set0_othername(GENERAL_NAME* gen, ASN1_OBJECT* oid,
+                                        ASN1_TYPE* value) {
+    WOLFSSL_ASN1_OBJECT *x = NULL;
+
+    if ((gen == NULL) || (oid == NULL) || (value == NULL)) {
+        return WOLFSSL_FAILURE;
+    }
+
+    x = wolfSSL_ASN1_OBJECT_dup(oid);
+    if (x == NULL) {
+        WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_dup() failed");
+        return WOLFSSL_FAILURE;
+    }
+
+    gen->type = GEN_OTHERNAME;
+    gen->d.otherName->type_id = x;
+    gen->d.otherName->value = value;
+    return WOLFSSL_SUCCESS;
+}
 
 /* return 1 on success 0 on fail */
 int wolfSSL_sk_GENERAL_NAME_push(WOLFSSL_GENERAL_NAMES* sk,
@@ -4153,6 +4345,19 @@ int wolfSSL_sk_GENERAL_NAME_num(WOLFSSL_STACK* sk)
     return (int)sk->num;
 }
 
+/* Allocates an empty GENERAL NAME stack */
+WOLFSSL_STACK* wolfSSL_sk_GENERAL_NAME_new(void *cmpFunc) {
+    WOLFSSL_STACK* sk = NULL;
+    (void)cmpFunc;
+    WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_new");
+
+    sk = wolfSSL_sk_new_null();
+    if (sk != NULL) {
+        sk->type = STACK_TYPE_GEN_NAME;
+    }
+
+    return sk;
+}
 #endif /* OPENSSL_EXTRA */
 
 #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
@@ -4363,34 +4568,52 @@ WOLFSSL_ACCESS_DESCRIPTION* wolfSSL_sk_ACCESS_DESCRIPTION_value(
 static void wolfSSL_GENERAL_NAME_type_free(WOLFSSL_GENERAL_NAME* name)
 {
     if (name != NULL) {
-        if (name->d.dNSName != NULL) {
+        switch (name->type) {
+        case GEN_IA5:
+            wolfSSL_ASN1_STRING_free(name->d.ia5);
+            name->d.ia5 = NULL;
+            break;
+        case GEN_EMAIL:
+            wolfSSL_ASN1_STRING_free(name->d.rfc822Name);
+            name->d.rfc822Name = NULL;
+            break;
+        case GEN_DNS:
             wolfSSL_ASN1_STRING_free(name->d.dNSName);
             name->d.dNSName = NULL;
-        }
-        if (name->d.dirn != NULL) {
+            break;
+        case GEN_DIRNAME:
             wolfSSL_X509_NAME_free(name->d.dirn);
             name->d.dirn = NULL;
-        }
-        if (name->d.uniformResourceIdentifier != NULL) {
+            break;
+        case GEN_URI:
             wolfSSL_ASN1_STRING_free(name->d.uniformResourceIdentifier);
             name->d.uniformResourceIdentifier = NULL;
-        }
-        if (name->d.iPAddress != NULL) {
+            break;
+        case GEN_IPADD:
             wolfSSL_ASN1_STRING_free(name->d.iPAddress);
             name->d.iPAddress = NULL;
-        }
-        if (name->d.registeredID != NULL) {
+            break;
+        case GEN_RID:
             wolfSSL_ASN1_OBJECT_free(name->d.registeredID);
             name->d.registeredID = NULL;
-        }
-        if (name->d.ia5 != NULL) {
-            wolfSSL_ASN1_STRING_free(name->d.ia5);
-            name->d.ia5 = 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;
+            break;
+        case GEN_X400:
+            /* Unsupported: fall through */
+        case GEN_EDIPARTY:
+            /* Unsupported: fall through */
+        default:
+            WOLFSSL_MSG("wolfSSL_GENERAL_NAME_type_free: possible leak");
+            break;
         }
     }
 }
 
-
 /* sets the general name type and free's the existing one
  * can fail with a memory error if malloc fails or bad arg error
  * otherwise return WOLFSSL_SUCCESS */
@@ -4409,6 +4632,7 @@ int wolfSSL_GENERAL_NAME_set_type(WOLFSSL_GENERAL_NAME* name, int typ)
                     ret = MEMORY_E;
                 break;
             default:
+                name->type = GEN_IA5;
                 name->d.ia5 = wolfSSL_ASN1_STRING_new();
                 if (name->d.ia5 == NULL)
                     ret = MEMORY_E;
@@ -7211,6 +7435,11 @@ static void *wolfSSL_d2i_X509_fp_ex(XFILE file, void **x509, int type)
             newx509 = (void *)wolfSSL_d2i_X509_CRL(NULL, fileBuffer, (int)sz);
         }
     #endif
+    #ifdef WOLFSSL_CERT_REQ
+        else if (type == CERTREQ_TYPE) {
+             newx509 = (void *)wolfSSL_X509_REQ_d2i(NULL, fileBuffer, (int)sz);
+        }
+    #endif
     #if !defined(NO_ASN) && !defined(NO_PWDBASED) && defined(HAVE_PKCS12)
         else if (type == PKCS12_TYPE) {
             if ((newx509 = wc_PKCS12_new()) == NULL) {
@@ -7249,11 +7478,20 @@ _exit:
     return newx509;
 }
 
+#ifdef WOLFSSL_CERT_REQ
+WOLFSSL_X509* wolfSSL_d2i_X509_REQ_fp(XFILE fp, WOLFSSL_X509 **req)
+{
+    return (WOLFSSL_X509 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)req,
+                                                  CERTREQ_TYPE);
+}
+#endif /* WOLFSSL_CERT_REQ */
+
 WOLFSSL_X509 *wolfSSL_d2i_X509_fp(XFILE fp, WOLFSSL_X509 **x509)
 {
     WOLFSSL_ENTER("wolfSSL_d2i_X509_fp");
     return (WOLFSSL_X509 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)x509, CERT_TYPE);
 }
+
 /* load certificate or CRL file, and add it to the STORE           */
 /* @param ctx    a pointer to X509_LOOKUP structure                */
 /* @param file   file name to load                                 */
@@ -9228,11 +9466,33 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref(
                     }
                 }
             }
+
+        #ifdef WOLFSSL_CUSTOM_OID
+            if (ret == WOLFSSL_SUCCESS) {
+                if ((req->customExtCount < 0) ||
+                    (req->customExtCount >= NUM_CUSTOM_EXT)) {
+                    WOLFSSL_MSG("Bad value for customExtCount.");
+                    ret = WOLFSSL_FAILURE;
+                }
+
+                if (ret == WOLFSSL_SUCCESS) {
+                    for (idx = 0; idx < req->customExtCount; idx++) {
+                        /* Note that ownership is NOT transfered.
+                         * req->custom_exts buffers still need to be cleaned
+                         * up. */
+                        cert->customCertExt[idx] = req->custom_exts[idx];
+                    }
+                    cert->customCertExtCount = req->customExtCount;
+                }
+            }
+        #endif /* WOLFSSL_CUSTOM_OID */
         #endif /* OPENSSL_ALL */
 
     #ifdef WOLFSSL_ALT_NAMES
-            cert->altNamesSz = FlattenAltNames(cert->altNames,
-                    sizeof(cert->altNames), req->altNames);
+            if (ret == WOLFSSL_SUCCESS) {
+                cert->altNamesSz = FlattenAltNames(cert->altNames,
+                        sizeof(cert->altNames), req->altNames);
+            }
     #endif /* WOLFSSL_ALT_NAMES */
         }
 

+ 142 - 1
tests/api.c

@@ -43264,6 +43264,142 @@ static int test_wolfSSL_X509_NAME_ENTRY(void)
     return res;
 }
 
+/* Note the lack of wolfSSL_ prefix...this is a compatability layer test. */
+static int test_GENERAL_NAME_set0_othername(void) {
+    int res = TEST_SKIPPED;
+#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)
+    const char * cert_fname = "./certs/server-cert.der";
+    const char * key_fname = "./certs/server-key.der";
+    X509* x509 = NULL;
+    GENERAL_NAME* gn = NULL;
+    GENERAL_NAMES* gns = NULL;
+    ASN1_OBJECT* upn_oid = NULL;
+    ASN1_UTF8STRING *utf8str = NULL;
+    ASN1_TYPE *value = NULL;
+    X509_EXTENSION * ext = NULL;
+
+    byte* pt = NULL;
+    byte der[4096];
+    int derSz = 0;
+    EVP_PKEY* priv = NULL;
+    FILE* f = NULL;
+
+    AssertNotNull(f = fopen(cert_fname, "rb"));
+    AssertNotNull(x509 = d2i_X509_fp(f, NULL));
+    fclose(f);
+    AssertNotNull(gn = GENERAL_NAME_new());
+    AssertNotNull(upn_oid = OBJ_txt2obj("1.3.6.1.4.1.311.20.2.3", 1));
+    AssertNotNull(utf8str = ASN1_UTF8STRING_new());
+    AssertIntEQ(ASN1_STRING_set(utf8str, "othername@wolfssl.com", -1), 1);
+    AssertNotNull(value = ASN1_TYPE_new());
+    ASN1_TYPE_set(value, V_ASN1_UTF8STRING, utf8str);
+    AssertIntEQ(GENERAL_NAME_set0_othername(gn, upn_oid, value), 1);
+    AssertNotNull(gns = sk_GENERAL_NAME_new(NULL));
+    AssertIntEQ(sk_GENERAL_NAME_push(gns, gn), 1);
+    AssertNotNull(ext = X509V3_EXT_i2d(NID_subject_alt_name, 0, gns));
+    AssertIntEQ(X509_add_ext(x509, ext, -1), 1);
+    AssertNotNull(f = fopen(key_fname, "rb"));
+    AssertIntGT(derSz = (int)fread(der, 1, sizeof(der), f), 0);
+    fclose(f);
+    pt = der;
+    AssertNotNull(priv = d2i_PrivateKey(EVP_PKEY_RSA, NULL,
+                                        (const unsigned char**)&pt, derSz));
+    AssertIntGT(X509_sign(x509, priv, EVP_sha256()), 0);
+    sk_GENERAL_NAME_pop_free(gns, GENERAL_NAME_free);
+    ASN1_OBJECT_free(upn_oid);
+    X509_EXTENSION_free(ext);
+    X509_free(x509);
+    EVP_PKEY_free(priv);
+    res = TEST_RES_CHECK(1);
+#endif
+    return res;
+}
+
+/* Note the lack of wolfSSL_ prefix...this is a compatability layer test. */
+static int test_othername_and_SID_ext(void) {
+    int res = TEST_SKIPPED;
+#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)
+
+    const char* csr_fname = "./certs/csr.signed.der";
+    const char* key_fname = "./certs/server-key.der";
+
+    byte der[4096];
+    int derSz = 0;
+    X509_REQ* x509 = NULL;
+    STACK_OF(X509_EXTENSION) *exts = NULL;
+
+    X509_EXTENSION * san_ext = NULL;
+    GENERAL_NAME* gn = NULL;
+    GENERAL_NAMES* gns = NULL;
+    ASN1_OBJECT* upn_oid = NULL;
+    ASN1_UTF8STRING *utf8str = NULL;
+    ASN1_TYPE *value = NULL;
+
+    /* SID extension. SID data format explained here:
+     * https://blog.qdsecurity.se/2022/05/27/manually-injecting-a-sid-in-a-certificate/
+     */
+    uint8_t SidExtension[] = {
+    48, 64, 160, 62, 6,  10, 43, 6,  1,  4,  1,  130, 55, 25, 2,  1,  160,
+    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};
+    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;
+
+    AssertNotNull(f = fopen(csr_fname, "rb"));
+    AssertNotNull(x509 = d2i_X509_REQ_fp(f, NULL));
+    fclose(f);
+    AssertIntEQ(X509_REQ_set_version(x509, 2), 1);
+    AssertNotNull(gn = GENERAL_NAME_new());
+    AssertNotNull(upn_oid = OBJ_txt2obj("1.3.6.1.4.1.311.20.2.3", 1));
+    AssertNotNull(utf8str = ASN1_UTF8STRING_new());
+    AssertIntEQ(ASN1_STRING_set(utf8str, "othername@wolfssl.com", -1), 1);
+    AssertNotNull(value = ASN1_TYPE_new());
+    ASN1_TYPE_set(value, V_ASN1_UTF8STRING, utf8str);
+    AssertIntEQ(GENERAL_NAME_set0_othername(gn, upn_oid, value), 1);
+    AssertNotNull(gns = sk_GENERAL_NAME_new(NULL));
+    AssertIntEQ(sk_GENERAL_NAME_push(gns, gn), 1);
+    AssertNotNull(san_ext = X509V3_EXT_i2d(NID_subject_alt_name, 0, gns));
+    AssertNotNull(sid_oid = OBJ_txt2obj("1.3.6.1.4.1.311.25.2", 1));
+    AssertNotNull(sid_data = ASN1_OCTET_STRING_new());
+    ASN1_OCTET_STRING_set(sid_data, SidExtension, sizeof(SidExtension));
+    AssertNotNull(sid_ext = X509_EXTENSION_create_by_OBJ(NULL, sid_oid, 0,
+                                                         sid_data));
+    AssertNotNull(exts = sk_X509_EXTENSION_new_null());
+    AssertIntEQ(sk_X509_EXTENSION_push(exts, san_ext), 1);
+    AssertIntEQ(sk_X509_EXTENSION_push(exts, sid_ext), 2);
+    AssertIntEQ(X509_REQ_add_extensions(x509, exts), 1);
+    AssertNotNull(f = fopen(key_fname, "rb"));
+    AssertIntGT(derSz = (int)fread(der, 1, sizeof(der), f), 0);
+    fclose(f);
+    pt = der;
+    AssertNotNull(priv = d2i_PrivateKey(EVP_PKEY_RSA, NULL,
+                                        (const unsigned char**)&pt, derSz));
+    AssertIntGT(X509_REQ_sign(x509, priv, EVP_sha256()), 0);
+    pt = der;
+    AssertIntGT(derSz = i2d_X509_REQ(x509, &pt), 0);
+    sk_GENERAL_NAME_pop_free(gns, GENERAL_NAME_free);
+    sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+    ASN1_OBJECT_free(upn_oid);
+    ASN1_OBJECT_free(sid_oid);
+    ASN1_OCTET_STRING_free(sid_data);
+    X509_REQ_free(x509);
+    EVP_PKEY_free(priv);
+    res = TEST_RES_CHECK(1);
+#endif
+    return res;
+}
 
 static int test_wolfSSL_X509_set_name(void)
 {
@@ -45135,7 +45271,6 @@ static int test_wolfSSL_GENERAL_NAME_print(void)
     const char* x400Str  = "X400Name:<unsupported>";
     const char* ediStr   = "EdiPartyName:<unsupported>";
 
-
     /* BIO to output */
     AssertNotNull(out = BIO_new(BIO_s_mem()));
 
@@ -45261,6 +45396,8 @@ static int test_wolfSSL_GENERAL_NAME_print(void)
     AssertIntGT(BIO_read(out, outbuf, sizeof(outbuf)), 0);
     AssertIntEQ(XSTRNCMP((const char*)outbuf, x400Str, XSTRLEN(x400Str)), 0);
 
+    /* Restore to GEN_IA5 (default) to avoid memory leak. */
+    gn->type = GEN_IA5;
     GENERAL_NAME_free(gn);
 
     /* test for GEN_EDIPARTY */
@@ -45273,6 +45410,8 @@ static int test_wolfSSL_GENERAL_NAME_print(void)
     AssertIntGT(BIO_read(out, outbuf, sizeof(outbuf)), 0);
     AssertIntEQ(XSTRNCMP((const char*)outbuf, ediStr, XSTRLEN(ediStr)), 0);
 
+    /* Restore to GEN_IA5 (default) to avoid memory leak. */
+    gn->type = GEN_IA5;
     GENERAL_NAME_free(gn);
 
     BIO_free(out);
@@ -65153,6 +65292,8 @@ TEST_CASE testCases[] = {
     TEST_DECL(test_wolfSSL_OBJ_txt2obj),
     TEST_DECL(test_wolfSSL_PEM_write_bio_X509),
     TEST_DECL(test_wolfSSL_X509_NAME_ENTRY),
+    TEST_DECL(test_GENERAL_NAME_set0_othername),
+    TEST_DECL(test_othername_and_SID_ext),
     TEST_DECL(test_wolfSSL_X509_set_name),
     TEST_DECL(test_wolfSSL_X509_set_notAfter),
     TEST_DECL(test_wolfSSL_X509_set_notBefore),

+ 44 - 1
wolfcrypt/src/asn.c

@@ -14574,6 +14574,49 @@ word32 SetExplicit(byte number, word32 len, byte* output)
                      output);
 }
 
+#if defined(OPENSSL_EXTRA)
+/* Encode an Othername into DER.
+ *
+ * @param [in]  name    Pointer to the WOLFSSL_ASN1_OTHERNAME to be encoded.
+ * @param [out] output  Buffer to encode into. If NULL, don't encode.
+ * @return  Number of bytes encoded or WOLFSSL_FAILURE if name parameter is bad.
+ */
+word32 SetOthername(void *name, byte *output)
+{
+    WOLFSSL_ASN1_OTHERNAME *nm = (WOLFSSL_ASN1_OTHERNAME *)name;
+    char *nameStr = NULL;
+    int nameSz = 0;
+    word32 len = 0;
+
+    if ((nm == NULL) || (nm->value == NULL)) {
+        WOLFSSL_MSG("otherName value is NULL");
+        return WOLFSSL_FAILURE;
+    }
+
+    nameStr = nm->value->value.utf8string->data;
+    nameSz = nm->value->value.utf8string->length;
+
+    len = nm->type_id->objSz +
+          SetHeader(ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC, nameSz + 2, NULL) +
+          SetHeader(CTC_UTF8, nameSz, NULL) + nameSz;
+
+    if (output != NULL) {
+        /* otherName OID */
+        XMEMCPY(output, nm->type_id->obj, nm->type_id->objSz);
+        output += nm->type_id->objSz;
+
+        output += SetHeader(ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC, nameSz + 2,
+                            output);
+
+        output += SetHeader(CTC_UTF8, nameSz, output);
+
+        XMEMCPY(output, nameStr, nameSz);
+        output += nameSz;
+    }
+
+    return len;
+}
+#endif /* OPENSSL_EXTRA */
 
 #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)
 
@@ -25949,7 +25992,7 @@ int FlattenAltNames(byte* output, word32 outputSz, const DNS_entry* names)
         i = idx;
 #endif
         output[idx] = (byte) (ASN_CONTEXT_SPECIFIC | curName->type);
-        if (curName->type == ASN_DIR_TYPE) {
+        if (curName->type == ASN_DIR_TYPE || curName->type == ASN_OTHER_TYPE) {
             output[idx] |= ASN_CONSTRUCTED;
         }
         idx++;

+ 4 - 0
wolfssl/internal.h

@@ -4802,6 +4802,10 @@ struct WOLFSSL_X509 {
     byte             authKeyIdSet:1;
     byte             authKeyIdCrit:1;
     byte             issuerSet:1;
+#ifdef WOLFSSL_CUSTOM_OID
+    CertExtension    custom_exts[NUM_CUSTOM_EXT];
+    int              customExtCount;
+#endif /* WOLFSSL_CUSTOM_OID */
 #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
 #ifdef WOLFSSL_CERT_REQ
     byte             isCSR:1;

+ 2 - 0
wolfssl/openssl/asn1.h

@@ -185,5 +185,7 @@ WOLFSSL_API int wolfSSL_ASN1_item_i2d(const void *src, byte **dest,
 
 #define BN_to_ASN1_INTEGER          wolfSSL_BN_to_ASN1_INTEGER
 #define ASN1_TYPE_set               wolfSSL_ASN1_TYPE_set
+#define ASN1_TYPE_new               wolfSSL_ASN1_TYPE_new
+#define ASN1_TYPE_free              wolfSSL_ASN1_TYPE_free
 
 #endif /* WOLFSSL_ASN1_H_ */

+ 20 - 11
wolfssl/openssl/ssl.h

@@ -110,7 +110,7 @@ typedef WOLFSSL_ASN1_BIT_STRING ASN1_BIT_STRING;
 typedef WOLFSSL_dynlock_value  CRYPTO_dynlock_value;
 typedef WOLFSSL_BUF_MEM        BUF_MEM;
 typedef WOLFSSL_GENERAL_NAMES  GENERAL_NAMES;
-typedef WOLFSSL_GENERAL_NAME GENERAL_NAME;
+typedef WOLFSSL_GENERAL_NAME   GENERAL_NAME;
 typedef WOLFSSL_OBJ_NAME       OBJ_NAME;
 typedef WOLFSSL_DIST_POINT_NAME DIST_POINT_NAME;
 typedef WOLFSSL_DIST_POINT      DIST_POINT;
@@ -392,16 +392,17 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS;
 #define SSL_SESSION_get_max_early_data  wolfSSL_SESSION_get_max_early_data
 
 #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
-    #define SSL_MODE_RELEASE_BUFFERS    0x00000010U
-    #define ASN1_BOOLEAN                WOLFSSL_ASN1_BOOLEAN
-    #define X509_get_ext                wolfSSL_X509_get_ext
-    #define X509_get_ext_by_OBJ         wolfSSL_X509_get_ext_by_OBJ
-    #define X509_cmp                    wolfSSL_X509_cmp
-    #define X509_EXTENSION_get_object   wolfSSL_X509_EXTENSION_get_object
-    #define X509_EXTENSION_get_critical wolfSSL_X509_EXTENSION_get_critical
-    #define X509_EXTENSION_get_data     wolfSSL_X509_EXTENSION_get_data
-    #define X509_EXTENSION_new          wolfSSL_X509_EXTENSION_new
-    #define X509_EXTENSION_free         wolfSSL_X509_EXTENSION_free
+    #define SSL_MODE_RELEASE_BUFFERS     0x00000010U
+    #define ASN1_BOOLEAN                 WOLFSSL_ASN1_BOOLEAN
+    #define X509_get_ext                 wolfSSL_X509_get_ext
+    #define X509_get_ext_by_OBJ          wolfSSL_X509_get_ext_by_OBJ
+    #define X509_cmp                     wolfSSL_X509_cmp
+    #define X509_EXTENSION_get_object    wolfSSL_X509_EXTENSION_get_object
+    #define X509_EXTENSION_get_critical  wolfSSL_X509_EXTENSION_get_critical
+    #define X509_EXTENSION_get_data      wolfSSL_X509_EXTENSION_get_data
+    #define X509_EXTENSION_new           wolfSSL_X509_EXTENSION_new
+    #define X509_EXTENSION_free          wolfSSL_X509_EXTENSION_free
+    #define X509_EXTENSION_create_by_OBJ wolfSSL_X509_EXTENSION_create_by_OBJ
 #endif
 
 #define DSA_dup_DH                      wolfSSL_DSA_dup_DH
@@ -415,6 +416,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS;
 #define i2d_X509_REQ_bio                wolfSSL_i2d_X509_REQ_bio
 #define d2i_X509_bio                    wolfSSL_d2i_X509_bio
 #define d2i_X509_REQ_bio                wolfSSL_d2i_X509_REQ_bio
+#define d2i_X509_REQ_fp                 wolfSSL_d2i_X509_REQ_fp
 #define d2i_X509_fp                     wolfSSL_d2i_X509_fp
 #define i2d_X509                        wolfSSL_i2d_X509
 #define d2i_X509                        wolfSSL_d2i_X509
@@ -878,6 +880,11 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_
 #define ASN1_OCTET_STRING_free          wolfSSL_ASN1_STRING_free
 #define ASN1_OCTET_STRING_set           wolfSSL_ASN1_STRING_set
 
+#define ASN1_UTF8STRING                 WOLFSSL_ASN1_STRING
+#define ASN1_UTF8STRING_new             wolfSSL_ASN1_STRING_new
+#define ASN1_UTF8STRING_free            wolfSSL_ASN1_STRING_free
+#define ASN1_UTF8STRING_set             wolfSSL_ASN1_STRING_set
+
 #define ASN1_PRINTABLE_type(...)        V_ASN1_PRINTABLESTRING
 
 #define ASN1_UTCTIME_pr                 wolfSSL_ASN1_UTCTIME_pr
@@ -1345,6 +1352,7 @@ typedef WOLFSSL_SRTP_PROTECTION_PROFILE      SRTP_PROTECTION_PROFILE;
 #define GENERAL_NAME_free               wolfSSL_GENERAL_NAME_free
 #define GENERAL_NAME_dup                wolfSSL_GENERAL_NAME_dup
 #define GENERAL_NAME_print              wolfSSL_GENERAL_NAME_print
+#define GENERAL_NAME_set0_othername     wolfSSL_GENERAL_NAME_set0_othername
 #define sk_GENERAL_NAME_push            wolfSSL_sk_GENERAL_NAME_push
 #define sk_GENERAL_NAME_value           wolfSSL_sk_GENERAL_NAME_value
 
@@ -1367,6 +1375,7 @@ typedef WOLFSSL_SRTP_PROTECTION_PROFILE      SRTP_PROTECTION_PROFILE;
 #define SSL_SESSION_set1_id_context     wolfSSL_SESSION_set1_id_context
 #define SSL_SESSION_print               wolfSSL_SESSION_print
 #define sk_GENERAL_NAME_pop_free        wolfSSL_sk_GENERAL_NAME_pop_free
+#define sk_GENERAL_NAME_new             wolfSSL_sk_GENERAL_NAME_new
 #define sk_GENERAL_NAME_free            wolfSSL_sk_GENERAL_NAME_free
 #define sk_ASN1_OBJECT_pop_free         wolfSSL_sk_ASN1_OBJECT_pop_free
 #define GENERAL_NAME_free               wolfSSL_GENERAL_NAME_free

+ 1 - 0
wolfssl/openssl/x509v3.h

@@ -109,6 +109,7 @@ struct WOLFSSL_X509_EXTENSION {
 #define GEN_URI         6
 #define GEN_IPADD       7
 #define GEN_RID         8
+#define GEN_IA5         9
 
 #define GENERAL_NAME       WOLFSSL_GENERAL_NAME
 

+ 11 - 0
wolfssl/ssl.h

@@ -1557,6 +1557,11 @@ WOLFSSL_API int wolfSSL_GENERAL_NAME_set_type(WOLFSSL_GENERAL_NAME* name,
         int typ);
 WOLFSSL_API WOLFSSL_GENERAL_NAMES* wolfSSL_GENERAL_NAMES_dup(
                                              WOLFSSL_GENERAL_NAMES* gns);
+WOLFSSL_API int wolfSSL_GENERAL_NAME_set0_othername(WOLFSSL_GENERAL_NAME* gen,
+                                                    WOLFSSL_ASN1_OBJECT* oid,
+                                                    WOLFSSL_ASN1_TYPE* value);
+
+WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_GENERAL_NAME_new(void *cmpFunc);
 WOLFSSL_API int wolfSSL_sk_GENERAL_NAME_push(WOLFSSL_GENERAL_NAMES* sk,
                                              WOLFSSL_GENERAL_NAME* gn);
 WOLFSSL_API WOLFSSL_GENERAL_NAME* wolfSSL_sk_GENERAL_NAME_value(
@@ -4279,6 +4284,9 @@ WOLFSSL_API int wolfSSL_X509_get_ext_by_OBJ(const WOLFSSL_X509 *x,
 WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x, int loc);
 WOLFSSL_API int wolfSSL_X509_EXTENSION_get_critical(const WOLFSSL_X509_EXTENSION* ex);
 WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_new(void);
+WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_create_by_OBJ(
+        WOLFSSL_X509_EXTENSION* ex, WOLFSSL_ASN1_OBJECT *obj, int crit,
+        WOLFSSL_ASN1_STRING *data);
 WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_dup(
         WOLFSSL_X509_EXTENSION* src);
 WOLFSSL_API int wolfSSL_sk_X509_EXTENSION_push(WOLFSSL_STACK* sk,
@@ -4316,6 +4324,9 @@ WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio,
 #ifdef WOLFSSL_CERT_REQ
 WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_REQ_bio(WOLFSSL_BIO* bio,
                                                WOLFSSL_X509** x509);
+#if !defined(NO_FILESYSTEM)
+WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_REQ_fp(XFILE fp, WOLFSSL_X509 **req);
+#endif
 #endif
 #endif /* OPENSSL_EXTRA || OPENSSL_ALL */
 

+ 3 - 0
wolfssl/wolfcrypt/asn.h

@@ -2166,6 +2166,9 @@ WOLFSSL_LOCAL word32 SetAlgoID(int algoOID,byte* output,int type,int curveSz);
 WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header);
 WOLFSSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output,
     word32 outputSz, int maxSnSz);
+/* name is of type WOLFSSL_ASN1_OTHERNAME; use void* to avoid including ssl.h */
+WOLFSSL_LOCAL word32 SetOthername(void *name, byte *output);
+
 #ifndef WOLFSSL_ASN_TEMPLATE
 WOLFSSL_LOCAL int wc_GetSerialNumber(const byte* input, word32* inOutIdx,
     byte* serial, int* serialSz, word32 maxIdx);

+ 10 - 12
wolfssl/wolfcrypt/asn_public.h

@@ -351,7 +351,6 @@ typedef struct NameAttrib {
 #endif /* WOLFSSL_MULTI_ATTRIB */
 #endif /* WOLFSSL_CERT_GEN || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
 
-#ifdef WOLFSSL_CERT_GEN
 #ifdef WOLFSSL_CUSTOM_OID
 typedef struct CertOidField {
     byte*  oid;
@@ -362,13 +361,12 @@ typedef struct CertOidField {
 } CertOidField;
 
 typedef struct CertExtension {
-    const char* oid;
-    byte        crit;
-    const byte* val;
-    int         valSz;
+    char* oid;
+    byte  crit;
+    byte* val;
+    int   valSz;
 } CertExtension;
 #endif
-#endif /* WOLFSSL_CERT_GEN */
 
 #if defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
 typedef struct CertName {
@@ -422,11 +420,8 @@ typedef struct CertName {
 } CertName;
 #endif /* WOLFSSL_CERT_GEN || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL*/
 
-#ifdef WOLFSSL_CERT_GEN
-
 #ifndef NUM_CUSTOM_EXT
 #define NUM_CUSTOM_EXT 16
-#endif
 
 /* for user to fill for certificate generation */
 typedef struct Cert {
@@ -434,10 +429,13 @@ typedef struct Cert {
     byte     serial[CTC_SERIAL_SIZE];   /* serial number */
     int      serialSz;                  /* serial size */
     int      sigType;                   /* signature algo type */
+#if defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA) \
+ || defined(OPENSSL_EXTRA_X509_SMALL)
     CertName issuer;                    /* issuer info */
+    CertName subject;                   /* subject info */
+#endif /* WOLFSSL_CERT_GEN || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
     int      daysValid;                 /* validity days */
     int      selfSigned;                /* self signed flag */
-    CertName subject;                   /* subject info */
     int      isCA;                      /* is this going to be a CA */
     byte     pathLen;                   /* max depth of valid certification
                                          * paths that include this cert */
@@ -492,7 +490,7 @@ typedef struct Cert {
     char     challengePw[CTC_NAME_SIZE];
     char     unstructuredName[CTC_NAME_SIZE];
     int      challengePwPrintableString; /* encode as PrintableString */
-#endif
+#endif /* WOLFSSL_CERT_REQ */
 #ifdef WOLFSSL_CUSTOM_OID
     /* user oid and value to go in req extensions */
     CertOidField extCustom;
@@ -500,7 +498,7 @@ typedef struct Cert {
     /* Extensions to go into X.509 certificates */
     CertExtension customCertExt[NUM_CUSTOM_EXT];
     int customCertExtCount;
-#endif
+#endif /* WOLFSSL_CUSTOM_OID */
     void*   decodedCert;      /* internal DecodedCert allocated from heap */
     byte*   der;              /* Pointer to buffer of current DecodedCert cache */
     void*   heap;             /* heap hint */