Browse Source

Merge pull request #6585 from cconlon/x509Ext

Fixes for WOLFSSL_X509 cert gen, WOLFSSL_ALT_NAMES to --enable-jni
JacobBarthelmeh 10 months ago
parent
commit
b889b27b8c
6 changed files with 221 additions and 88 deletions
  1. 3 0
      configure.ac
  2. 3 0
      src/ssl_asn1.c
  3. 47 5
      src/x509.c
  4. 32 1
      tests/api.c
  5. 128 82
      wolfcrypt/src/asn.c
  6. 8 0
      wolfssl/wolfcrypt/asn.h

+ 3 - 0
configure.ac

@@ -5850,6 +5850,9 @@ then
         ENABLED_ALPN="yes"
         AM_CFLAGS="$AM_CFLAGS -DHAVE_ALPN"
     fi
+
+    # cert gen requires alt names
+    ENABLED_ALTNAMES="yes"
 fi
 
 if test "$ENABLED_LIGHTY" = "yes"

+ 3 - 0
src/ssl_asn1.c

@@ -1606,6 +1606,9 @@ WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_dup(WOLFSSL_ASN1_OBJECT* obj)
         dupl->grp   = obj->grp;
         dupl->nid   = obj->nid;
         dupl->objSz = obj->objSz;
+    #ifdef OPENSSL_EXTRA
+        dupl->ca    = obj->ca;
+    #endif
         /* Check for encoding. */
         if (obj->obj) {
             /* Allocate memory for ASN.1 OBJECT_ID DER encoding. */

+ 47 - 5
src/x509.c

@@ -1360,11 +1360,45 @@ int wolfSSL_X509_add_ext(WOLFSSL_X509 *x509, WOLFSSL_X509_EXTENSION *ext, int lo
         break;
     }
     case NID_key_usage:
-        if (ext && ext->value.data &&
-                ext->value.length == sizeof(word16)) {
-            x509->keyUsage = *(word16*)ext->value.data;
-            x509->keyUsageCrit = (byte)ext->crit;
-            x509->keyUsageSet = 1;
+        if (ext && ext->value.data) {
+            if (ext->value.length == sizeof(word16)) {
+                /* if ext->value is already word16, set directly */
+                x509->keyUsage = *(word16*)ext->value.data;
+                x509->keyUsageCrit = (byte)ext->crit;
+                x509->keyUsageSet = 1;
+            }
+            else if (ext->value.length > 0) {
+                /* ext->value is comma-delimited string, convert to word16 */
+                if (ParseKeyUsageStr(ext->value.data, &x509->keyUsage,
+                                     x509->heap) != 0) {
+                    return WOLFSSL_FAILURE;
+                }
+                x509->keyUsageCrit = (byte)ext->crit;
+                x509->keyUsageSet = 1;
+            }
+            else {
+                return WOLFSSL_FAILURE;
+            }
+        }
+        break;
+    case NID_ext_key_usage:
+        if (ext && ext->value.data) {
+            if (ext->value.length == sizeof(byte)) {
+                /* if ext->value is already word16, set directly */
+                x509->extKeyUsage = *(byte*)ext->value.data;
+                x509->extKeyUsageCrit = (byte)ext->crit;
+            }
+            else if (ext->value.length > 0) {
+                /* ext->value is comma-delimited string, convert to word16 */
+                if (ParseExtKeyUsageStr(ext->value.data, &x509->extKeyUsage,
+                                        x509->heap) != 0) {
+                    return WOLFSSL_FAILURE;
+                }
+                x509->extKeyUsageCrit = (byte)ext->crit;
+            }
+            else {
+                return WOLFSSL_FAILURE;
+            }
         }
         break;
     case NID_basic_constraints:
@@ -2781,6 +2815,14 @@ static WOLFSSL_X509_EXTENSION* createExtFromStr(int nid, const char *value)
             }
             ext->value.type = KEY_USAGE_OID;
             break;
+        case NID_ext_key_usage:
+            if (wolfSSL_ASN1_STRING_set(&ext->value, value, -1)
+                    != WOLFSSL_SUCCESS) {
+                WOLFSSL_MSG("wolfSSL_ASN1_STRING_set error");
+                goto err_cleanup;
+            }
+            ext->value.type = EXT_KEY_USAGE_OID;
+            break;
         default:
             WOLFSSL_MSG("invalid or unsupported NID");
             goto err_cleanup;

+ 32 - 1
tests/api.c

@@ -46255,6 +46255,7 @@ static int test_wolfSSL_X509V3_EXT_nconf(void)
         "authorityKeyIdentifier",
         "subjectAltName",
         "keyUsage",
+        "extendedKeyUsage",
     };
     size_t ext_names_count = sizeof(ext_names)/sizeof(*ext_names);
     int ext_nids[] = {
@@ -46262,20 +46263,43 @@ static int test_wolfSSL_X509V3_EXT_nconf(void)
         NID_authority_key_identifier,
         NID_subject_alt_name,
         NID_key_usage,
+        NID_ext_key_usage,
     };
     size_t ext_nids_count = sizeof(ext_nids)/sizeof(*ext_nids);
     const char *ext_values[] = {
         "hash",
         "hash",
         "DNS:example.com, IP:127.0.0.1",
-        "digitalSignature,keyEncipherment,dataEncipherment",
+        "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,"
+            "keyAgreement,keyCertSign,cRLSign,encipherOnly,decipherOnly",
+        "serverAuth,clientAuth,codeSigning,emailProtection,timeStamping,"
+            "OCSPSigning",
     };
     size_t i;
     X509_EXTENSION* ext = NULL;
     X509* x509 = NULL;
+    unsigned int keyUsageFlags;
+    unsigned int extKeyUsageFlags;
 
     ExpectNotNull(x509 = X509_new());
 
+    /* keyUsage / extKeyUsage should match string above */
+    keyUsageFlags = KU_DIGITAL_SIGNATURE
+                  | KU_NON_REPUDIATION
+                  | KU_KEY_ENCIPHERMENT
+                  | KU_DATA_ENCIPHERMENT
+                  | KU_KEY_AGREEMENT
+                  | KU_KEY_CERT_SIGN
+                  | KU_CRL_SIGN
+                  | KU_ENCIPHER_ONLY
+                  | KU_DECIPHER_ONLY;
+    extKeyUsageFlags = XKU_SSL_CLIENT
+                     | XKU_SSL_SERVER
+                     | XKU_CODE_SIGN
+                     | XKU_SMIME
+                     | XKU_TIMESTAMP
+                     | XKU_OCSP_SIGN;
+
     for (i = 0; i < ext_names_count; i++) {
         ExpectNotNull(ext = X509V3_EXT_nconf(NULL, NULL, ext_names[i],
             ext_values[i]));
@@ -46295,6 +46319,13 @@ static int test_wolfSSL_X509V3_EXT_nconf(void)
         ExpectNotNull(ext = X509V3_EXT_nconf(NULL, NULL, ext_names[i],
             ext_values[i]));
         ExpectIntEQ(X509_add_ext(x509, ext, -1), WOLFSSL_SUCCESS);
+
+        if (ext_nids[i] == NID_key_usage) {
+            ExpectIntEQ(X509_get_key_usage(x509), keyUsageFlags);
+        }
+        else if (ext_nids[i] == NID_ext_key_usage) {
+            ExpectIntEQ(X509_get_extended_key_usage(x509), extKeyUsageFlags);
+        }
         X509_EXTENSION_free(ext);
         ext = NULL;
     }

+ 128 - 82
wolfcrypt/src/asn.c

@@ -26647,6 +26647,132 @@ int wc_EncodeNameCanonical(EncodedName* name, const char* nameStr,
 }
 #endif /* WOLFSSL_CERT_GEN || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
 
+#if (defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT)) || \
+    (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA))
+
+/* Convert key usage string (comma delimited, null terminated) to word16
+ * Returns 0 on success, negative on error */
+int ParseKeyUsageStr(const char* value, word16* keyUsage, void* heap)
+{
+    int ret = 0;
+    char *token, *str, *ptr;
+    word32 len = 0;
+    word16 usage = 0;
+
+    if (value == NULL || keyUsage == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* duplicate string (including terminator) */
+    len = (word32)XSTRLEN(value);
+    str = (char*)XMALLOC(len + 1, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (str == NULL) {
+        return MEMORY_E;
+    }
+    XMEMCPY(str, value, len + 1);
+
+    /* parse value, and set corresponding Key Usage value */
+    if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
+        XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return KEYUSAGE_E;
+    }
+    while (token != NULL) {
+        if (!XSTRCASECMP(token, "digitalSignature"))
+            usage |= KEYUSE_DIGITAL_SIG;
+        else if (!XSTRCASECMP(token, "nonRepudiation") ||
+                 !XSTRCASECMP(token, "contentCommitment"))
+            usage |= KEYUSE_CONTENT_COMMIT;
+        else if (!XSTRCASECMP(token, "keyEncipherment"))
+            usage |= KEYUSE_KEY_ENCIPHER;
+        else if (!XSTRCASECMP(token, "dataEncipherment"))
+            usage |= KEYUSE_DATA_ENCIPHER;
+        else if (!XSTRCASECMP(token, "keyAgreement"))
+            usage |= KEYUSE_KEY_AGREE;
+        else if (!XSTRCASECMP(token, "keyCertSign"))
+            usage |= KEYUSE_KEY_CERT_SIGN;
+        else if (!XSTRCASECMP(token, "cRLSign"))
+            usage |= KEYUSE_CRL_SIGN;
+        else if (!XSTRCASECMP(token, "encipherOnly"))
+            usage |= KEYUSE_ENCIPHER_ONLY;
+        else if (!XSTRCASECMP(token, "decipherOnly"))
+            usage |= KEYUSE_DECIPHER_ONLY;
+        else {
+            ret = KEYUSAGE_E;
+            break;
+        }
+
+        token = XSTRTOK(NULL, ",", &ptr);
+    }
+
+    XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if (ret == 0) {
+        *keyUsage = usage;
+    }
+
+    return ret;
+}
+
+/* Convert extended key usage string (comma delimited, null terminated) to byte
+ * Returns 0 on success, negative on error */
+int ParseExtKeyUsageStr(const char* value, byte* extKeyUsage, void* heap)
+{
+    int ret = 0;
+    char *token, *str, *ptr;
+    word32 len = 0;
+    byte usage = 0;
+
+    if (value == NULL || extKeyUsage == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    /* duplicate string (including terminator) */
+    len = (word32)XSTRLEN(value);
+    str = (char*)XMALLOC(len + 1, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    if (str == NULL) {
+        return MEMORY_E;
+    }
+    XMEMCPY(str, value, len + 1);
+
+    /* parse value, and set corresponding Key Usage value */
+    if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
+        XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        return EXTKEYUSAGE_E;
+    }
+    while (token != NULL) {
+        if (!XSTRCASECMP(token, "any"))
+            usage |= EXTKEYUSE_ANY;
+        else if (!XSTRCASECMP(token, "serverAuth"))
+            usage |= EXTKEYUSE_SERVER_AUTH;
+        else if (!XSTRCASECMP(token, "clientAuth"))
+            usage |= EXTKEYUSE_CLIENT_AUTH;
+        else if (!XSTRCASECMP(token, "codeSigning"))
+            usage |= EXTKEYUSE_CODESIGN;
+        else if (!XSTRCASECMP(token, "emailProtection"))
+            usage |= EXTKEYUSE_EMAILPROT;
+        else if (!XSTRCASECMP(token, "timeStamping"))
+            usage |= EXTKEYUSE_TIMESTAMP;
+        else if (!XSTRCASECMP(token, "OCSPSigning"))
+            usage |= EXTKEYUSE_OCSP_SIGN;
+        else {
+            ret = EXTKEYUSAGE_E;
+            break;
+        }
+
+        token = XSTRTOK(NULL, ",", &ptr);
+    }
+
+    XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
+
+    if (ret == 0) {
+        *extKeyUsage = usage;
+    }
+
+    return ret;
+}
+
+#endif /* (CERT_GEN && CERT_EXT) || (OPENSSL_ALL || OPENSSL_EXTRA) */
+
 #ifdef WOLFSSL_CERT_GEN
 /* Encodes one attribute of the name (issuer/subject)
  * call we_EncodeName_ex with 0x16, IA5String for email type
@@ -30471,56 +30597,14 @@ int wc_SetAuthKeyId(Cert *cert, const char* file)
 int wc_SetKeyUsage(Cert *cert, const char *value)
 {
     int ret = 0;
-    char *token, *str, *ptr;
-    word32 len;
 
     if (cert == NULL || value == NULL)
         return BAD_FUNC_ARG;
 
     cert->keyUsage = 0;
 
-    /* duplicate string (including terminator) */
-    len = (word32)XSTRLEN(value);
-    str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (str == NULL)
-        return MEMORY_E;
-    XMEMCPY(str, value, len+1);
-
-    /* parse value, and set corresponding Key Usage value */
-    if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
-        XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return KEYUSAGE_E;
-    }
-    while (token != NULL)
-    {
-        if (!XSTRCASECMP(token, "digitalSignature"))
-            cert->keyUsage |= KEYUSE_DIGITAL_SIG;
-        else if (!XSTRCASECMP(token, "nonRepudiation") ||
-                 !XSTRCASECMP(token, "contentCommitment"))
-            cert->keyUsage |= KEYUSE_CONTENT_COMMIT;
-        else if (!XSTRCASECMP(token, "keyEncipherment"))
-            cert->keyUsage |= KEYUSE_KEY_ENCIPHER;
-        else if (!XSTRCASECMP(token, "dataEncipherment"))
-            cert->keyUsage |= KEYUSE_DATA_ENCIPHER;
-        else if (!XSTRCASECMP(token, "keyAgreement"))
-            cert->keyUsage |= KEYUSE_KEY_AGREE;
-        else if (!XSTRCASECMP(token, "keyCertSign"))
-            cert->keyUsage |= KEYUSE_KEY_CERT_SIGN;
-        else if (!XSTRCASECMP(token, "cRLSign"))
-            cert->keyUsage |= KEYUSE_CRL_SIGN;
-        else if (!XSTRCASECMP(token, "encipherOnly"))
-            cert->keyUsage |= KEYUSE_ENCIPHER_ONLY;
-        else if (!XSTRCASECMP(token, "decipherOnly"))
-            cert->keyUsage |= KEYUSE_DECIPHER_ONLY;
-        else {
-            ret = KEYUSAGE_E;
-            break;
-        }
-
-        token = XSTRTOK(NULL, ",", &ptr);
-    }
+    ret = ParseKeyUsageStr(value, &cert->keyUsage, cert->heap);
 
-    XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
     return ret;
 }
 
@@ -30528,52 +30612,14 @@ int wc_SetKeyUsage(Cert *cert, const char *value)
 int wc_SetExtKeyUsage(Cert *cert, const char *value)
 {
     int ret = 0;
-    char *token, *str, *ptr;
-    word32 len;
 
     if (cert == NULL || value == NULL)
         return BAD_FUNC_ARG;
 
     cert->extKeyUsage = 0;
 
-    /* duplicate string (including terminator) */
-    len = (word32)XSTRLEN(value);
-    str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (str == NULL)
-        return MEMORY_E;
-    XMEMCPY(str, value, len+1);
-
-    /* parse value, and set corresponding Key Usage value */
-    if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
-        XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return EXTKEYUSAGE_E;
-    }
-
-    while (token != NULL)
-    {
-        if (!XSTRCASECMP(token, "any"))
-            cert->extKeyUsage |= EXTKEYUSE_ANY;
-        else if (!XSTRCASECMP(token, "serverAuth"))
-            cert->extKeyUsage |= EXTKEYUSE_SERVER_AUTH;
-        else if (!XSTRCASECMP(token, "clientAuth"))
-            cert->extKeyUsage |= EXTKEYUSE_CLIENT_AUTH;
-        else if (!XSTRCASECMP(token, "codeSigning"))
-            cert->extKeyUsage |= EXTKEYUSE_CODESIGN;
-        else if (!XSTRCASECMP(token, "emailProtection"))
-            cert->extKeyUsage |= EXTKEYUSE_EMAILPROT;
-        else if (!XSTRCASECMP(token, "timeStamping"))
-            cert->extKeyUsage |= EXTKEYUSE_TIMESTAMP;
-        else if (!XSTRCASECMP(token, "OCSPSigning"))
-            cert->extKeyUsage |= EXTKEYUSE_OCSP_SIGN;
-        else {
-            ret = EXTKEYUSAGE_E;
-            break;
-        }
-
-        token = XSTRTOK(NULL, ",", &ptr);
-    }
+    ret = ParseExtKeyUsageStr(value, &cert->extKeyUsage, cert->heap);
 
-    XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
     return ret;
 }
 

+ 8 - 0
wolfssl/wolfcrypt/asn.h

@@ -2287,6 +2287,14 @@ WOLFSSL_LOCAL int PemToDer(const unsigned char* buff, long sz, int type,
 WOLFSSL_LOCAL int AllocDer(DerBuffer** der, word32 length, int type, void* heap);
 WOLFSSL_LOCAL void FreeDer(DerBuffer** der);
 
+#if (defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT)) || \
+    (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA))
+WOLFSSL_LOCAL int ParseKeyUsageStr(const char* value, word16* keyUsage,
+        void* heap);
+WOLFSSL_LOCAL int ParseExtKeyUsageStr(const char* value, byte* extKeyUsage,
+        void* heap);
+#endif /* (CERT_GEN && CERT_EXT) || (OPENSSL_ALL || OPENSSL_EXTRA) */
+
 #endif /* !NO_CERTS */
 
 #ifdef HAVE_SMIME