Index: azure_iot_hub_f767zi/trunk/wolfssl-4.7.0/wolfcrypt/src/asn.c
===================================================================
--- azure_iot_hub_f767zi/trunk/wolfssl-4.4.0/wolfcrypt/src/asn.c	(revision 457)
+++ azure_iot_hub_f767zi/trunk/wolfssl-4.7.0/wolfcrypt/src/asn.c	(revision 464)
@@ -20,5 +20,12 @@
  */
 
-
+/*
+
+DESCRIPTION
+This library provides the interface to Abstract Syntax Notation One (ASN.1) objects.
+ASN.1 is a standard interface description language for defining data structures
+that can be serialized and deserialized in a cross-platform way.
+
+*/
 #ifdef HAVE_CONFIG_H
     #include <config.h>
@@ -67,4 +74,5 @@
 #include <wolfssl/wolfcrypt/des3.h>
 #include <wolfssl/wolfcrypt/aes.h>
+#include <wolfssl/wolfcrypt/rc2.h>
 #include <wolfssl/wolfcrypt/wc_encrypt.h>
 #include <wolfssl/wolfcrypt/logging.h>
@@ -114,4 +122,10 @@
 #endif
 
+#ifndef NO_DSA
+    #include <wolfssl/wolfcrypt/dsa.h>
+#else
+    typedef void* DsaKey;
+#endif
+
 #ifdef WOLF_CRYPTO_CB
     #include <wolfssl/wolfcrypt/cryptocb.h>
@@ -129,7 +143,8 @@
 #define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; }
 
-#if defined(HAVE_SELFTEST) || ( !defined(NO_SKID) && \
-                                ( !defined(HAVE_FIPS) || \
-                                  !defined(HAVE_FIPS_VERSION) ))
+#if !defined(NO_SKID) && (!defined(HAVE_FIPS) || !defined(HAVE_FIPS_VERSION))
+    #if !defined(HAVE_SELFTEST) || (defined(HAVE_SELFTEST) && \
+                                   (!defined(HAVE_SELFTEST_VERSION) || \
+                                    HAVE_SELFTEST_VERSION < 2))
     #ifndef WOLFSSL_AES_KEY_SIZE_ENUM
     #define WOLFSSL_AES_KEY_SIZE_ENUM
@@ -141,4 +156,5 @@
     };
     #endif
+    #endif /* HAVE_SELFTEST */
 #endif
 #ifdef WOLFSSL_RENESAS_TSIP_TLS
@@ -456,4 +472,15 @@
 
     if (*len > 0) {
+
+#ifndef WOLFSSL_ASN_INT_LEAD_0_ANY
+        /* check for invalid padding on negative integer.
+         * c.f. X.690 (ISO/IEC 8825-2:2003 (E)) 10.4.6; RFC 5280 4.1
+         */
+        if (*len > 1) {
+            if ((input[*inOutIdx] == 0xff) && (input[*inOutIdx + 1] & 0x80))
+                return ASN_PARSE_E;
+        }
+#endif
+
         /* remove leading zero, unless there is only one 0x00 byte */
         if ((input[*inOutIdx] == 0x00) && (*len > 1)) {
@@ -461,6 +488,8 @@
             (*len)--;
 
+#ifndef WOLFSSL_ASN_INT_LEAD_0_ANY
             if (*len > 0 && (input[*inOutIdx] & 0x80) == 0)
                 return ASN_PARSE_E;
+#endif
         }
     }
@@ -502,4 +531,5 @@
 #if !defined(NO_DSA) && !defined(NO_SHA)
 static const char sigSha1wDsaName[] = "SHAwDSA";
+static const char sigSha256wDsaName[] = "SHA256wDSA";
 #endif /* NO_DSA */
 #ifndef NO_RSA
@@ -555,4 +585,6 @@
         case CTC_SHAwDSA:
             return sigSha1wDsaName;
+        case CTC_SHA256wDSA:
+            return sigSha256wDsaName;
     #endif /* NO_DSA && NO_SHA */
     #ifndef NO_RSA
@@ -625,5 +657,5 @@
  * returns the number of bytes added to the buffer.
  */
-static int SetASNInt(int len, byte firstByte, byte* output)
+int SetASNInt(int len, byte firstByte, byte* output)
 {
     word32 idx = 0;
@@ -668,4 +700,6 @@
     leadingBit = mp_leading_bit(n);
     length = mp_unsigned_bin_size(n);
+    if (maxSz >= 0 && (1 + length + (leadingBit ? 1 : 0)) > maxSz)
+        return BUFFER_E;
     idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output);
     if (maxSz >= 0 && (idx + length) > maxSz)
@@ -840,6 +874,16 @@
 
     if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
+        int ret;
+
         *inOutIdx = ++idx;  /* skip header */
-        return GetMyVersion(input, inOutIdx, version, maxIdx);
+        ret = GetMyVersion(input, inOutIdx, version, maxIdx);
+        if (ret >= 0) {
+            /* check if version is expected value rfc 5280 4.1 {0, 1, 2} */
+            if (*version > MAX_X509_VERSION || *version < MIN_X509_VERSION) {
+                WOLFSSL_MSG("Unexpected certificate version");
+                ret = ASN_VERSION_E;
+            }
+        }
+        return ret;
     }
 
@@ -881,6 +925,6 @@
 
 #if (!defined(WOLFSSL_KEY_GEN) && !defined(OPENSSL_EXTRA) && defined(RSA_LOW_MEM)) \
-    || defined(WOLFSSL_RSA_PUBLIC_ONLY) || (!defined(NO_DSA) && defined(WOLFSSL_QT))
-#if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
+    || defined(WOLFSSL_RSA_PUBLIC_ONLY) || (!defined(NO_DSA))
+#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || !defined(NO_DSA)
 static int SkipInt(const byte* input, word32* inOutIdx, word32 maxIdx)
 {
@@ -900,5 +944,5 @@
 #endif
 
-static int CheckBitString(const byte* input, word32* inOutIdx, int* len,
+int CheckBitString(const byte* input, word32* inOutIdx, int* len,
                           word32 maxIdx, int zeroBits, byte* unusedBits)
 {
@@ -956,5 +1000,6 @@
     (defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)) || \
     ((defined(HAVE_ED25519) || defined(HAVE_ED448)) && \
-        (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)))
+        (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA))) || \
+    (!defined(NO_DSA) && !defined(HAVE_SELFTEST) && defined(WOLFSSL_KEY_GEN))
 
 /* Set the DER/BER encoding of the ASN.1 BIT_STRING header.
@@ -1158,5 +1203,5 @@
 
 #ifdef WOLFSSL_SMALL_STACK
-    indefItems = XMALLOC(sizeof(IndefItems), NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    indefItems = (IndefItems *)XMALLOC(sizeof(IndefItems), NULL, DYNAMIC_TYPE_TMP_BUFFER);
     if (indefItems == NULL) {
         ret = MEMORY_E;
@@ -1357,10 +1402,5 @@
 #endif
 
-#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)
-
-#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || \
-    defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
-
-#ifdef WOLFSSL_CERT_EXT
+#if defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN)
 /* Set the DER/BER encoding of the ASN.1 BIT_STRING with a 16-bit value.
  *
@@ -1395,9 +1435,5 @@
     return idx;
 }
-#endif /* WOLFSSL_CERT_EXT */
-#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 || defined(HAVE_ED448) */
-#endif /* WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN */
-
-
+#endif /* WOLFSSL_CERT_EXT || WOLFSSL_CERT_GEN */
 
 /* hashType */
@@ -1443,4 +1479,5 @@
 #if !defined(NO_DSA) && !defined(NO_SHA)
     static const byte sigSha1wDsaOid[] = {42, 134, 72, 206, 56, 4, 3};
+    static const byte sigSha256wDsaOid[] = {96, 134, 72, 1, 101, 3, 4, 3, 2};
 #endif /* NO_DSA */
 #ifndef NO_RSA
@@ -1510,7 +1547,7 @@
     static const byte keyEd448Oid[] = {43, 101, 113};
 #endif /* HAVE_ED448 */
-#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+#ifndef NO_DH
     static const byte keyDhOid[] = {42, 134, 72, 134, 247, 13, 1, 3, 1};
-#endif /* ! NO_DH ... */
+#endif /* !NO_DH */
 
 /* curveType */
@@ -1594,6 +1631,7 @@
 /* ocspType */
 #ifdef HAVE_OCSP
-    static const byte ocspBasicOid[] = {43, 6, 1, 5, 5, 7, 48, 1, 1};
-    static const byte ocspNonceOid[] = {43, 6, 1, 5, 5, 7, 48, 1, 2};
+    static const byte ocspBasicOid[]    = {43, 6, 1, 5, 5, 7, 48, 1, 1};
+    static const byte ocspNonceOid[]    = {43, 6, 1, 5, 5, 7, 48, 1, 2};
+    static const byte ocspNoCheckOid[]  = {43, 6, 1, 5, 5, 7, 48, 1, 5};
 #endif /* HAVE_OCSP */
 
@@ -1633,4 +1671,10 @@
 static const byte extExtKeyUsageTimestampOid[]    = {43, 6, 1, 5, 5, 7, 3, 8};
 static const byte extExtKeyUsageOcspSignOid[]     = {43, 6, 1, 5, 5, 7, 3, 9};
+
+#ifdef WOLFSSL_CERT_REQ
+/* csrAttrType */
+static const byte attrChallengePasswordOid[] = {42, 134, 72, 134, 247, 13, 1, 9, 7};
+static const byte attrSerialNumberOid[] = {85, 4, 5};
+#endif
 
 /* kdfType */
@@ -1725,4 +1769,8 @@
                     oid = sigSha1wDsaOid;
                     *oidSz = sizeof(sigSha1wDsaOid);
+                    break;
+                case CTC_SHA256wDSA:
+                    oid = sigSha256wDsaOid;
+                    *oidSz = sizeof(sigSha256wDsaOid);
                     break;
                 #endif /* NO_DSA */
@@ -1858,10 +1906,10 @@
                     break;
                 #endif /* HAVE_ED448 */
-                #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+                #ifndef NO_DH
                 case DHk:
                     oid = keyDhOid;
                     *oidSz = sizeof(keyDhOid);
                     break;
-                #endif /* ! NO_DH && (WOLFSSL_QT || OPENSSL_ALL */
+                #endif /* !NO_DH */
                 default:
                     break;
@@ -2015,4 +2063,10 @@
                     break;
             #endif
+            #ifdef HAVE_OCSP
+                case OCSP_NOCHECK_OID:
+                    oid = ocspNoCheckOid;
+                    *oidSz = sizeof(ocspNoCheckOid);
+                    break;
+            #endif
             }
             break;
@@ -2255,4 +2309,18 @@
             break;
 #endif /* WOLFSSL_APACHE_HTTPD */
+#ifdef WOLFSSL_CERT_REQ
+        case oidCsrAttrType:
+            switch (id) {
+                case CHALLENGE_PASSWORD_OID:
+                    oid = attrChallengePasswordOid;
+                    *oidSz = sizeof(attrChallengePasswordOid);
+                    break;
+                case SERIAL_NUMBER_OID:
+                    oid = attrSerialNumberOid;
+                    *oidSz = sizeof(attrSerialNumberOid);
+                    break;
+            }
+            break;
+#endif
         case oidIgnoreType:
         default:
@@ -2422,6 +2490,9 @@
     int idx = 0;
 
-    output[idx++] = ASN_OBJECT_ID;
-    idx += SetLength(len, output + idx);
+    if (output)
+        output[idx++] = ASN_OBJECT_ID;
+    else
+        idx++;
+    idx += SetLength(len, output ? output + idx : NULL);
 
     return idx;
@@ -2570,5 +2641,5 @@
     int version, length;
 
-    if (inOutIdx == NULL) {
+    if (inOutIdx == NULL || input == NULL || key == NULL) {
         return BAD_FUNC_ARG;
     }
@@ -2683,4 +2754,7 @@
     if (length < 0)
         return length;
+
+    if (length + inOutIdx > sz)
+        return BUFFER_E;
 
     XMEMMOVE(input, input + inOutIdx, length);
@@ -2831,17 +2905,22 @@
 
 #if defined(HAVE_PKCS12) || !defined(NO_CHECK_PRIVATE_KEY)
-/* check that the private key is a pair for the public key in certificate
+/* check that the private key is a pair for the public key
  * return 1 (true) on match
  * return 0 or negative value on failure/error
  *
- * key   : buffer holding DER format key
- * keySz : size of key buffer
- * der   : a initialized and parsed DecodedCert holding a certificate */
-int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der)
+ * privKey   : buffer holding DER format private key
+ * privKeySz : size of private key buffer
+ * pubKey    : buffer holding DER format public key
+ * pubKeySz  : size of public key buffer
+ * ks        : type of key */
+int wc_CheckPrivateKey(const byte* privKey, word32 privKeySz,
+                       const byte* pubKey, word32 pubKeySz, enum Key_Sum ks)
 {
     int ret;
-    (void)keySz;
-
-    if (key == NULL || der == NULL) {
+    (void)privKeySz;
+    (void)pubKeySz;
+    (void)ks;
+
+    if (privKey == NULL || pubKey == NULL) {
         return BAD_FUNC_ARG;
     }
@@ -2849,5 +2928,5 @@
     #if !defined(NO_RSA) && !defined(NO_ASN_CRYPT)
     /* test if RSA key */
-    if (der->keyOID == RSAk) {
+    if (ks == RSAk) {
     #ifdef WOLFSSL_SMALL_STACK
         RsaKey* a;
@@ -2884,10 +2963,10 @@
             return ret;
         }
-        if ((ret = wc_RsaPrivateKeyDecode(key, &keyIdx, a, keySz)) == 0) {
+        if ((ret = wc_RsaPrivateKeyDecode(privKey, &keyIdx, a, privKeySz)) == 0) {
             WOLFSSL_MSG("Checking RSA key pair");
             keyIdx = 0; /* reset to 0 for parsing public key */
 
-            if ((ret = wc_RsaPublicKeyDecode(der->publicKey, &keyIdx, b,
-                                                       der->pubKeySize)) == 0) {
+            if ((ret = wc_RsaPublicKeyDecode(pubKey, &keyIdx, b,
+                    pubKeySz)) == 0) {
                 /* limit for user RSA crypto because of RsaKey
                  * dereference. */
@@ -2918,5 +2997,5 @@
 
     #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT)
-    if (der->keyOID == ECDSAk) {
+    if (ks == ECDSAk) {
     #ifdef WOLFSSL_SMALL_STACK
         ecc_key* key_pair;
@@ -2948,6 +3027,6 @@
         }
 
-        if ((ret = wc_EccPrivateKeyDecode(key, &keyIdx, key_pair,
-                                                                 keySz)) == 0) {
+        if ((ret = wc_EccPrivateKeyDecode(privKey, &keyIdx, key_pair,
+                privKeySz)) == 0) {
             WOLFSSL_MSG("Checking ECC key pair");
 
@@ -2957,7 +3036,7 @@
                 ret = wc_ecc_init(key_pair);
                 if (ret == 0) {
-                    ret = wc_ecc_import_private_key((const byte*)privDer,
-                                            privSz, (const byte*)der->publicKey,
-                                            der->pubKeySize, key_pair);
+                    ret = wc_ecc_import_private_key(privDer,
+                                            privSz, pubKey,
+                                            pubKeySz, key_pair);
                 }
 
@@ -2983,5 +3062,5 @@
 
     #if defined(HAVE_ED25519) && !defined(NO_ASN_CRYPT)
-    if (der->keyOID == ED25519k) {
+    if (ks == ED25519k) {
     #ifdef WOLFSSL_SMALL_STACK
         ed25519_key* key_pair;
@@ -3004,10 +3083,10 @@
             return ret;
         }
-        if ((ret = wc_Ed25519PrivateKeyDecode(key, &keyIdx, key_pair,
-                                                                 keySz)) == 0) {
+        if ((ret = wc_Ed25519PrivateKeyDecode(privKey, &keyIdx, key_pair,
+                privKeySz)) == 0) {
             WOLFSSL_MSG("Checking ED25519 key pair");
             keyIdx = 0;
-            if ((ret = wc_ed25519_import_public(der->publicKey, der->pubKeySize,
-                                                              key_pair)) == 0) {
+            if ((ret = wc_ed25519_import_public(pubKey, pubKeySz,
+                    key_pair)) == 0) {
                 /* public and private extracted successfully no check if is
                  * a pair and also do sanity checks on key. wc_ecc_check_key
@@ -3026,5 +3105,5 @@
 
     #if defined(HAVE_ED448) && !defined(NO_ASN_CRYPT)
-    if (der->keyOID == ED448k) {
+    if (ks == ED448k) {
     #ifdef WOLFSSL_SMALL_STACK
         ed448_key* key_pair = NULL;
@@ -3047,10 +3126,10 @@
             return ret;
         }
-        if ((ret = wc_Ed448PrivateKeyDecode(key, &keyIdx, key_pair,
-                                                                 keySz)) == 0) {
+        if ((ret = wc_Ed448PrivateKeyDecode(privKey, &keyIdx, key_pair,
+                privKeySz)) == 0) {
             WOLFSSL_MSG("Checking ED448 key pair");
             keyIdx = 0;
-            if ((ret = wc_ed448_import_public(der->publicKey, der->pubKeySize,
-                                                              key_pair)) == 0) {
+            if ((ret = wc_ed448_import_public(pubKey, pubKeySz,
+                    key_pair)) == 0) {
                 /* public and private extracted successfully no check if is
                  * a pair and also do sanity checks on key. wc_ecc_check_key
@@ -3071,7 +3150,22 @@
     }
 
-    (void)keySz;
-
     return ret;
+}
+
+/* check that the private key is a pair for the public key in certificate
+ * return 1 (true) on match
+ * return 0 or negative value on failure/error
+ *
+ * key   : buffer holding DER format key
+ * keySz : size of key buffer
+ * der   : a initialized and parsed DecodedCert holding a certificate */
+int wc_CheckPrivateKeyCert(const byte* key, word32 keySz, DecodedCert* der)
+{
+    if (key == NULL || der == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    return wc_CheckPrivateKey(key, keySz, der->publicKey,
+            der->pubKeySize, (enum Key_Sum) der->keyOID);
 }
 
@@ -3110,4 +3204,11 @@
             return 0;
     #endif
+    #ifdef WC_RC2
+        case PBE_SHA1_40RC2_CBC:
+            *id = PBE_SHA1_40RC2_CBC;
+            *version = PKCS12v1;
+            if (blockSz) *blockSz = RC2_BLOCK_SIZE;
+            return 0;
+    #endif
 #endif /* !NO_SHA */
         default:
@@ -3197,8 +3298,10 @@
     #if !defined(NO_RSA) && !defined(NO_ASN_CRYPT)
     {
-        RsaKey rsa;
-
-        wc_InitRsaKey(&rsa, heap);
-        if (wc_RsaPrivateKeyDecode(key, &tmpIdx, &rsa, keySz) == 0) {
+        RsaKey *rsa = (RsaKey *)XMALLOC(sizeof *rsa, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (rsa == NULL)
+            return MEMORY_E;
+
+        wc_InitRsaKey(rsa, heap);
+        if (wc_RsaPrivateKeyDecode(key, &tmpIdx, rsa, keySz) == 0) {
             *algoID = RSAk;
         }
@@ -3206,20 +3309,24 @@
             WOLFSSL_MSG("Not RSA DER key");
         }
-        wc_FreeRsaKey(&rsa);
+        wc_FreeRsaKey(rsa);
+        XFREE(rsa, heap, DYNAMIC_TYPE_TMP_BUFFER);
     }
     #endif /* !NO_RSA && !NO_ASN_CRYPT */
     #if defined(HAVE_ECC) && !defined(NO_ASN_CRYPT)
     if (*algoID == 0) {
-        ecc_key ecc;
+        ecc_key *ecc = (ecc_key *)XMALLOC(sizeof *ecc, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (ecc == NULL)
+            return MEMORY_E;
 
         tmpIdx = 0;
-        wc_ecc_init_ex(&ecc, heap, INVALID_DEVID);
-        if (wc_EccPrivateKeyDecode(key, &tmpIdx, &ecc, keySz) == 0) {
+        wc_ecc_init_ex(ecc, heap, INVALID_DEVID);
+        if (wc_EccPrivateKeyDecode(key, &tmpIdx, ecc, keySz) == 0) {
             *algoID = ECDSAk;
 
             /* now find oid */
-            if (wc_ecc_get_oid(ecc.dp->oidSum, curveOID, oidSz) < 0) {
+            if (wc_ecc_get_oid(ecc->dp->oidSum, curveOID, oidSz) < 0) {
                 WOLFSSL_MSG("Error getting ECC curve OID");
-                wc_ecc_free(&ecc);
+                wc_ecc_free(ecc);
+                XFREE(ecc, heap, DYNAMIC_TYPE_TMP_BUFFER);
                 return BAD_FUNC_ARG;
             }
@@ -3228,15 +3335,17 @@
             WOLFSSL_MSG("Not ECC DER key either");
         }
-        wc_ecc_free(&ecc);
+        wc_ecc_free(ecc);
+        XFREE(ecc, heap, DYNAMIC_TYPE_TMP_BUFFER);
     }
 #endif /* HAVE_ECC && !NO_ASN_CRYPT */
 #if defined(HAVE_ED25519) && !defined(NO_ASN_CRYPT)
     if (*algoID != RSAk && *algoID != ECDSAk) {
-        ed25519_key ed25519;
+        ed25519_key *ed25519 = (ed25519_key *)XMALLOC(sizeof *ed25519, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (ed25519 == NULL)
+            return MEMORY_E;
 
         tmpIdx = 0;
-        if (wc_ed25519_init(&ed25519) == 0) {
-            if (wc_Ed25519PrivateKeyDecode(key, &tmpIdx, &ed25519, keySz)
-                                                                         == 0) {
+        if (wc_ed25519_init(ed25519) == 0) {
+            if (wc_Ed25519PrivateKeyDecode(key, &tmpIdx, ed25519, keySz) == 0) {
                 *algoID = ED25519k;
             }
@@ -3244,18 +3353,21 @@
                 WOLFSSL_MSG("Not ED25519 DER key");
             }
-            wc_ed25519_free(&ed25519);
+            wc_ed25519_free(ed25519);
         }
         else {
             WOLFSSL_MSG("GetKeyOID wc_ed25519_init failed");
         }
+        XFREE(ed25519, heap, DYNAMIC_TYPE_TMP_BUFFER);
     }
 #endif /* HAVE_ED25519 && !NO_ASN_CRYPT */
 #if defined(HAVE_ED448) && !defined(NO_ASN_CRYPT)
     if (*algoID != RSAk && *algoID != ECDSAk && *algoID != ED25519k) {
-        ed448_key ed448;
+        ed448_key *ed448 = (ed448_key *)XMALLOC(sizeof *ed448, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        if (ed448 == NULL)
+            return MEMORY_E;
 
         tmpIdx = 0;
-        if (wc_ed448_init(&ed448) == 0) {
-            if (wc_Ed448PrivateKeyDecode(key, &tmpIdx, &ed448, keySz) == 0) {
+        if (wc_ed448_init(ed448) == 0) {
+            if (wc_Ed448PrivateKeyDecode(key, &tmpIdx, ed448, keySz) == 0) {
                 *algoID = ED448k;
             }
@@ -3263,9 +3375,10 @@
                 WOLFSSL_MSG("Not ED448 DER key");
             }
-            wc_ed448_free(&ed448);
+            wc_ed448_free(ed448);
         }
         else {
             WOLFSSL_MSG("GetKeyOID wc_ed448_init failed");
         }
+        XFREE(ed448, heap, DYNAMIC_TYPE_TMP_BUFFER);
     }
 #endif /* HAVE_ED448 && !NO_ASN_CRYPT */
@@ -3405,4 +3518,8 @@
         ret = SetShortInt(out, &inOutIdx, itt, *outSz);
         if (ret < 0) {
+        #ifdef WOLFSSL_SMALL_STACK
+            if (saltTmp != NULL)
+                XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        #endif
             return ret;
         }
@@ -3428,4 +3545,8 @@
     if ((ret = wc_GetKeyOID(key, keySz, &curveOID, &oidSz, &algoID, heap))< 0) {
         WOLFSSL_MSG("Error getting key OID");
+    #ifdef WOLFSSL_SMALL_STACK
+        if (saltTmp != NULL)
+            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
         return ret;
     }
@@ -3454,4 +3575,8 @@
         *outSz = tmpSz + MAX_ALGO_SZ + MAX_LENGTH_SZ +MAX_LENGTH_SZ + MAX_SEQ_SZ
             + MAX_LENGTH_SZ + MAX_SEQ_SZ + 3;
+    #ifdef WOLFSSL_SMALL_STACK
+        if (saltTmp != NULL)
+            XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
         return LENGTH_ONLY_E;
     }
@@ -3487,5 +3612,5 @@
         if (saltTmp != NULL)
             XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(salt, heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
         return MEMORY_E;
     }
@@ -4390,12 +4515,18 @@
 
 #ifndef NO_DH
-
+/* Supports either:
+ * - DH params G/P (PKCS#3 DH) file or
+ * - DH key file (if WOLFSSL_DH_EXTRA enabled) */
+/* The wc_DhParamsLoad function also loads DH params, but directly into buffers, not DhKey */
 int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz)
 {
     int ret = 0;
     int length;
-    #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+#ifdef WOLFSSL_DH_EXTRA
+    #if !defined(HAVE_FIPS) || \
+        (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))
     word32 oid = 0, temp = 0;
     #endif
+#endif
 
     WOLFSSL_ENTER("wc_DhKeyDecode");
@@ -4407,19 +4538,33 @@
         return ASN_PARSE_E;
 
-    #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+#ifdef WOLFSSL_DH_EXTRA
+    #if !defined(HAVE_FIPS) || \
+        (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))
     temp = *inOutIdx;
     #endif
-
+#endif
     /* Assume input started after 1.2.840.113549.1.3.1 dhKeyAgreement */
-    if (GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
-        GetInt(&key->g,  input, inOutIdx, inSz) < 0) {
+    if (GetInt(&key->p, input, inOutIdx, inSz) < 0) {
         ret = ASN_DH_KEY_E;
     }
-
-    #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+    if (ret == 0 && GetInt(&key->g, input, inOutIdx, inSz) < 0) {
+        mp_clear(&key->p);
+        ret = ASN_DH_KEY_E;
+    }
+
+#ifdef WOLFSSL_DH_EXTRA
+    #if !defined(HAVE_FIPS) || \
+        (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))
     /* If ASN_DH_KEY_E: Check if input started at beginning of key */
     if (ret == ASN_DH_KEY_E) {
-        /* rewind back to after the first sequence */
         *inOutIdx = temp;
+
+        /* the version (0) */
+        if (GetASNInt(input, inOutIdx, &length, inSz) < 0) {
+            return ASN_PARSE_E;
+        }
+        *inOutIdx += length;
+
+        /* Size of dhKeyAgreement section */
         if (GetSequence(input, inOutIdx, &length, inSz) < 0)
             return ASN_PARSE_E;
@@ -4433,6 +4578,9 @@
             return ASN_PARSE_E;
 
-        if (GetInt(&key->p,  input, inOutIdx, inSz) < 0 ||
-            GetInt(&key->g,  input, inOutIdx, inSz) < 0) {
+        if (GetInt(&key->p, input, inOutIdx, inSz) < 0) {
+            return ASN_DH_KEY_E;
+        }
+        if (ret == 0 && GetInt(&key->g, input, inOutIdx, inSz) < 0) {
+            mp_clear(&key->p);
             return ASN_DH_KEY_E;
         }
@@ -4454,5 +4602,7 @@
             if (GetInt(&key->priv, input, inOutIdx, inSz) == 0) {
                 WOLFSSL_MSG("Found Private Key");
-                ret = 0;
+
+                /* Compute public */
+                ret = mp_exptmod(&key->g, &key->priv, &key->p, &key->pub);
             }
         } else {
@@ -4462,11 +4612,11 @@
         }
     }
-    #endif /* WOLFSSL_QT || OPENSSL_ALL */
-
-    WOLFSSL_MSG("wc_DhKeyDecode Success");
+    #endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */
+#endif /* WOLFSSL_DH_EXTRA */
+
+    WOLFSSL_LEAVE("wc_DhKeyDecode", ret);
 
     return ret;
 }
-
 
 int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz,
@@ -4507,5 +4657,5 @@
     return 0;
 }
-#endif /* NO_DH */
+#endif /* !NO_DH */
 
 
@@ -4663,5 +4813,6 @@
 }
 
-#if !defined(HAVE_SELFTEST) && defined(WOLFSSL_KEY_GEN)
+#if !defined(HAVE_SELFTEST) && (defined(WOLFSSL_KEY_GEN) || \
+        defined(WOLFSSL_CERT_GEN))
 /* Write a public DSA key to output */
 int wc_SetDsaPublicKey(byte* output, DsaKey* key,
@@ -4852,5 +5003,5 @@
     return wc_SetDsaPublicKey(output, key, inLen, 1);
 }
-#endif /* !HAVE_SELFTEST && WOLFSSL_KEY_GEN */
+#endif /* !HAVE_SELFTEST && (WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN) */
 
 /* Convert private DsaKey key to DER format, write to output (inLen),
@@ -4999,4 +5150,6 @@
     if (cert->altEmailNames)
         FreeAltNames(cert->altEmailNames, cert->heap);
+    if (cert->altDirNames)
+        FreeAltNames(cert->altDirNames, cert->heap);
     if (cert->permittedNames)
         FreeNameSubtrees(cert->permittedNames, cert->heap);
@@ -5009,9 +5162,10 @@
     XFREE(cert->hwSerialNum, cert->heap, DYNAMIC_TYPE_X509_EXT);
 #endif /* WOLFSSL_SEP */
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-    if (cert->issuerName.fullName != NULL)
-        XFREE(cert->issuerName.fullName, cert->heap, DYNAMIC_TYPE_X509);
-    if (cert->subjectName.fullName != NULL)
-        XFREE(cert->subjectName.fullName, cert->heap, DYNAMIC_TYPE_X509);
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+    !defined(WOLFCRYPT_ONLY)
+    if (cert->issuerName != NULL)
+        wolfSSL_X509_NAME_free((WOLFSSL_X509_NAME*)cert->issuerName);
+    if (cert->subjectName != NULL)
+        wolfSSL_X509_NAME_free((WOLFSSL_X509_NAME*)cert->subjectName);
 #endif /* OPENSSL_EXTRA */
 #ifdef WOLFSSL_RENESAS_TSIP_TLS
@@ -5101,8 +5255,8 @@
 {
     int length;
-#if !defined(NO_DSA) && defined(WOLFSSL_QT)
+#ifndef NO_DSA
     int tmpLen;
 #endif
-#if defined(HAVE_ECC) || defined(HAVE_NTRU)
+#if defined(HAVE_ECC) || defined(HAVE_NTRU) || !defined(NO_DSA)
     int tmpIdx = cert->srcIdx;
 #endif
@@ -5111,5 +5265,5 @@
         return ASN_PARSE_E;
 
-#if !defined(NO_DSA) && defined(WOLFSSL_QT)
+#ifndef NO_DSA
     tmpLen = length + 4;
 #endif
@@ -5324,5 +5478,5 @@
         }
     #endif /* HAVE_ED448 */
-    #if !defined(NO_DSA) && defined(WOLFSSL_QT)
+    #ifndef NO_DSA
         case DSAk:
         {
@@ -5357,6 +5511,7 @@
             return 0;
         }
-    #endif /* NO_DSA && QT */
+    #endif /* NO_DSA */
         default:
+            WOLFSSL_MSG("Unknown or not compiled in key OID");
             return ASN_UNKNOWN_OID_E;
     }
@@ -5449,7 +5604,8 @@
         {WOLFSSL_EMAIL_ADDR, NID_emailAddress},
         {NULL, -1}};
-
     int i;
     #ifdef HAVE_ECC
+    char curveName[16]; /* Same as MAX_CURVE_NAME_SZ but can't include that
+                         * symbol in this file */
     int eccEnum;
     #endif
@@ -5464,9 +5620,18 @@
     if (XSTRNCMP(sn, "prime256v1", 10) == 0)
         sn = "SECP256R1";
-    if (XSTRNCMP(sn, "secp384r1", 10) == 0)
-        sn = "SECP384R1";
+    /* OpenSSL allows lowercase curve names */
+    for (i = 0; i < (int)(sizeof(curveName) - 1) && *sn; i++) {
+        curveName[i] = (char)XTOUPPER(*sn++);
+    }
+    curveName[i] = '\0';
     /* find based on name and return NID */
-    for (i = 0; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++) {
-        if (XSTRNCMP(sn, ecc_sets[i].name, ECC_MAXNAME) == 0) {
+    for (i = 0;
+#ifndef WOLFSSL_ECC_CURVE_STATIC
+         ecc_sets[i].size != 0 && ecc_sets[i].name != NULL;
+#else
+         ecc_sets[i].size != 0;
+#endif
+         i++) {
+        if (XSTRNCMP(curveName, ecc_sets[i].name, ECC_MAXNAME) == 0) {
             eccEnum = ecc_sets[i].id;
             /* Convert enum value in ecc_curve_id to OpenSSL NID */
@@ -5484,12 +5649,4 @@
 {
     int ret;
-
-#ifdef WOLF_CRYPTO_CB
-    /* try to use a registered crypto callback */
-    ret = wc_CryptoCb_Sha256Hash(NULL, data, len, hash);
-    if (ret != CRYPTOCB_UNAVAILABLE)
-        return ret;
-    /* fall-through when unavailable */
-#endif
 
 #if defined(NO_SHA) && !defined(NO_SHA256)
@@ -5504,6 +5661,7 @@
 }
 
-/* process NAME, either issuer or subject */
-static int GetName(DecodedCert* cert, int nameType, int maxIdx)
+/* process NAME, either issuer or subject
+ * returns 0 on success and negative values on fail */
+int GetName(DecodedCert* cert, int nameType, int maxIdx)
 {
     int    length;  /* length of all distinguished names */
@@ -5514,12 +5672,8 @@
     word32 idx, localIdx = 0;
     byte   tag;
-    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-        DecodedName* dName =
-                  (nameType == ISSUER) ? &cert->issuerName : &cert->subjectName;
-        int dcnum = 0;
-        #ifdef OPENSSL_EXTRA
-        int count = 0;
-        #endif
-    #endif /* OPENSSL_EXTRA */
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+            !defined(WOLFCRYPT_ONLY)
+    WOLFSSL_X509_NAME* dName;
+#endif /* OPENSSL_EXTRA */
 
     WOLFSSL_MSG("Getting Cert Name");
@@ -5578,4 +5732,11 @@
     }
 #endif
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+    !defined(WOLFCRYPT_ONLY)
+    dName = wolfSSL_X509_NAME_new();
+    if (dName == NULL) {
+        return MEMORY_E;
+    }
+#endif /* OPENSSL_EXTRA */
 
     while (cert->srcIdx < (word32)length) {
@@ -5588,4 +5749,9 @@
         int         strLen  = 0;
         byte        id      = 0;
+    #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \
+                && !defined(WOLFCRYPT_ONLY)
+         int        nid = NID_undef;
+         int        enc;
+    #endif /* OPENSSL_EXTRA */
 
         if (GetSet(cert->source, &cert->srcIdx, &dummy, maxIdx) < 0) {
@@ -5593,14 +5759,29 @@
         }
 
-        if (GetSequence(cert->source, &cert->srcIdx, &dummy, maxIdx) <= 0)
+        if (GetSequence(cert->source, &cert->srcIdx, &dummy, maxIdx) <= 0) {
+        #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+            !defined(WOLFCRYPT_ONLY)
+            wolfSSL_X509_NAME_free(dName);
+        #endif /* OPENSSL_EXTRA */
             return ASN_PARSE_E;
+        }
 
         ret = GetASNObjectId(cert->source, &cert->srcIdx, &oidSz, maxIdx);
-        if (ret != 0)
+        if (ret != 0) {
+        #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+            !defined(WOLFCRYPT_ONLY)
+            wolfSSL_X509_NAME_free(dName);
+        #endif /* OPENSSL_EXTRA */
             return ret;
+        }
 
         /* make sure there is room for joint */
-        if ((cert->srcIdx + sizeof(joint)) > (word32)maxIdx)
+        if ((cert->srcIdx + sizeof(joint)) > (word32)maxIdx) {
+        #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+            !defined(WOLFCRYPT_ONLY)
+            wolfSSL_X509_NAME_free(dName);
+        #endif /* OPENSSL_EXTRA */
             return ASN_PARSE_E;
+        }
 
         XMEMCPY(joint, &cert->source[cert->srcIdx], sizeof(joint));
@@ -5612,4 +5793,8 @@
             if (GetHeader(cert->source, &b, &cert->srcIdx, &strLen,
                           maxIdx, 1) < 0) {
+            #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+            !defined(WOLFCRYPT_ONLY)
+                wolfSSL_X509_NAME_free(dName);
+            #endif /* OPENSSL_EXTRA */
                 return ASN_PARSE_E;
             }
@@ -5624,8 +5809,8 @@
                 copy = WOLFSSL_COMMON_NAME;
                 copyLen = sizeof(WOLFSSL_COMMON_NAME) - 1;
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->cnIdx = cert->srcIdx;
-                    dName->cnLen = strLen;
-                #endif /* OPENSSL_EXTRA */
+            #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \
+                && !defined(WOLFCRYPT_ONLY)
+                nid = NID_commonName;
+            #endif /* OPENSSL_EXTRA */
             }
             else if (id == ASN_SUR_NAME) {
@@ -5639,7 +5824,8 @@
                     }
                 #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->snIdx = cert->srcIdx;
-                    dName->snLen = strLen;
+                #if (defined(OPENSSL_EXTRA) || \
+                        defined(OPENSSL_EXTRA_X509_SMALL)) \
+                        && !defined(WOLFCRYPT_ONLY)
+                    nid = NID_surname;
                 #endif /* OPENSSL_EXTRA */
             }
@@ -5654,7 +5840,8 @@
                     }
                 #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->cIdx = cert->srcIdx;
-                    dName->cLen = strLen;
+                #if (defined(OPENSSL_EXTRA) || \
+                        defined(OPENSSL_EXTRA_X509_SMALL)) \
+                        && !defined(WOLFCRYPT_ONLY)
+                    nid = NID_countryName;
                 #endif /* OPENSSL_EXTRA */
             }
@@ -5669,7 +5856,8 @@
                     }
                 #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->lIdx = cert->srcIdx;
-                    dName->lLen = strLen;
+                #if (defined(OPENSSL_EXTRA) || \
+                        defined(OPENSSL_EXTRA_X509_SMALL)) \
+                        && !defined(WOLFCRYPT_ONLY)
+                    nid = NID_localityName;
                 #endif /* OPENSSL_EXTRA */
             }
@@ -5684,7 +5872,8 @@
                     }
                 #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->stIdx = cert->srcIdx;
-                    dName->stLen = strLen;
+                #if (defined(OPENSSL_EXTRA) || \
+                        defined(OPENSSL_EXTRA_X509_SMALL)) \
+                        && !defined(WOLFCRYPT_ONLY)
+                    nid = NID_stateOrProvinceName;
                 #endif /* OPENSSL_EXTRA */
             }
@@ -5699,7 +5888,8 @@
                     }
                 #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->oIdx = cert->srcIdx;
-                    dName->oLen = strLen;
+                #if (defined(OPENSSL_EXTRA) || \
+                        defined(OPENSSL_EXTRA_X509_SMALL)) \
+                        && !defined(WOLFCRYPT_ONLY)
+                    nid = NID_organizationName;
                 #endif /* OPENSSL_EXTRA */
             }
@@ -5714,7 +5904,8 @@
                     }
                 #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->ouIdx = cert->srcIdx;
-                    dName->ouLen = strLen;
+                #if (defined(OPENSSL_EXTRA) || \
+                        defined(OPENSSL_EXTRA_X509_SMALL)) \
+                        && !defined(WOLFCRYPT_ONLY)
+                    nid = NID_organizationalUnitName;
                 #endif /* OPENSSL_EXTRA */
             }
@@ -5729,7 +5920,8 @@
                     }
                 #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->snIdx = cert->srcIdx;
-                    dName->snLen = strLen;
+                #if (defined(OPENSSL_EXTRA) || \
+                        defined(OPENSSL_EXTRA_X509_SMALL)) \
+                        && !defined(WOLFCRYPT_ONLY)
+                    nid = NID_serialNumber;
                 #endif /* OPENSSL_EXTRA */
             }
@@ -5745,7 +5937,7 @@
                 }
             #endif /* WOLFSSL_CERT_GEN */
-            #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                dName->bcIdx = cert->srcIdx;
-                dName->bcLen = strLen;
+            #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \
+                        && !defined(WOLFCRYPT_ONLY)
+                nid = NID_businessCategory;
             #endif /* OPENSSL_EXTRA */
             }
@@ -5764,6 +5956,11 @@
 
             if (GetLength(cert->source, &cert->srcIdx, &strLen,
-                          maxIdx) < 0)
+                          maxIdx) < 0) {
+            #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+            !defined(WOLFCRYPT_ONLY)
+                wolfSSL_X509_NAME_free(dName);
+            #endif /* OPENSSL_EXTRA */
                 return ASN_PARSE_E;
+            }
 
             /* Check for jurisdiction of incorporation country name */
@@ -5778,7 +5975,8 @@
                     }
                 #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->jcIdx = cert->srcIdx;
-                    dName->jcLen = strLen;
+                #if (defined(OPENSSL_EXTRA) || \
+                        defined(OPENSSL_EXTRA_X509_SMALL)) \
+                        && !defined(WOLFCRYPT_ONLY)
+                    nid = NID_jurisdictionCountryName;
                 #endif /* OPENSSL_EXTRA */
             }
@@ -5795,7 +5993,8 @@
                     }
                 #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->jsIdx = cert->srcIdx;
-                    dName->jsLen = strLen;
+                #if (defined(OPENSSL_EXTRA) || \
+                        defined(OPENSSL_EXTRA_X509_SMALL)) \
+                        && !defined(WOLFCRYPT_ONLY)
+                    nid = NID_jurisdictionStateOrProvinceName;
                 #endif /* OPENSSL_EXTRA */
             }
@@ -5825,6 +6024,11 @@
             cert->srcIdx += oidSz + 1;
 
-            if (GetLength(cert->source, &cert->srcIdx, &strLen, maxIdx) < 0)
+            if (GetLength(cert->source, &cert->srcIdx, &strLen, maxIdx) < 0) {
+            #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+            !defined(WOLFCRYPT_ONLY)
+                wolfSSL_X509_NAME_free(dName);
+            #endif /* OPENSSL_EXTRA */
                 return ASN_PARSE_E;
+            }
 
             if (strLen > (int)(ASN_NAME_MAX - idx)) {
@@ -5849,7 +6053,8 @@
                     }
                 #endif /* WOLFSSL_CERT_GEN */
-                #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-                    dName->emailIdx = cert->srcIdx;
-                    dName->emailLen = strLen;
+                #if (defined(OPENSSL_EXTRA) || \
+                        defined(OPENSSL_EXTRA_X509_SMALL)) \
+                        && !defined(WOLFCRYPT_ONLY)
+                    nid = NID_emailAddress;
                 #endif /* OPENSSL_EXTRA */
                 #ifndef IGNORE_NAME_CONSTRAINTS
@@ -5861,4 +6066,9 @@
                         if (emailName == NULL) {
                             WOLFSSL_MSG("\tOut of Memory");
+                        #if (defined(OPENSSL_EXTRA) || \
+                                defined(OPENSSL_EXTRA_X509_SMALL)) && \
+                                !defined(WOLFCRYPT_ONLY)
+                            wolfSSL_X509_NAME_free(dName);
+                        #endif /* OPENSSL_EXTRA */
                             return MEMORY_E;
                         }
@@ -5869,4 +6079,9 @@
                             WOLFSSL_MSG("\tOut of Memory");
                             XFREE(emailName, cert->heap, DYNAMIC_TYPE_ALTNAME);
+                        #if (defined(OPENSSL_EXTRA) || \
+                                defined(OPENSSL_EXTRA_X509_SMALL)) && \
+                                !defined(WOLFCRYPT_ONLY)
+                            wolfSSL_X509_NAME_free(dName);
+                        #endif /* OPENSSL_EXTRA */
                             return MEMORY_E;
                         }
@@ -5887,8 +6102,8 @@
                         copy = WOLFSSL_USER_ID;
                         copyLen = sizeof(WOLFSSL_USER_ID) - 1;
-                    #if defined(OPENSSL_EXTRA) || \
-                        defined(OPENSSL_EXTRA_X509_SMALL)
-                        dName->uidIdx = cert->srcIdx;
-                        dName->uidLen = strLen;
+                    #if (defined(OPENSSL_EXTRA) || \
+                        defined(OPENSSL_EXTRA_X509_SMALL)) \
+                        && !defined(WOLFCRYPT_ONLY)
+                        nid = NID_userId;
                     #endif /* OPENSSL_EXTRA */
                         break;
@@ -5897,10 +6112,8 @@
                         copy = WOLFSSL_DOMAIN_COMPONENT;
                         copyLen = sizeof(WOLFSSL_DOMAIN_COMPONENT) - 1;
-                    #if defined(OPENSSL_EXTRA) || \
-                        defined(OPENSSL_EXTRA_X509_SMALL)
-                        dName->dcIdx[dcnum] = cert->srcIdx;
-                        dName->dcLen[dcnum] = strLen;
-                        dName->dcNum = dcnum + 1;
-                        dcnum++;
+                    #if (defined(OPENSSL_EXTRA) || \
+                        defined(OPENSSL_EXTRA_X509_SMALL)) \
+                        && !defined(WOLFCRYPT_ONLY)
+                        nid = NID_domainComponent;
                     #endif /* OPENSSL_EXTRA */
                         break;
@@ -5908,4 +6121,9 @@
                     default:
                         WOLFSSL_MSG("Unknown pilot attribute type");
+                    #if (defined(OPENSSL_EXTRA) || \
+                                defined(OPENSSL_EXTRA_X509_SMALL)) && \
+                                !defined(WOLFCRYPT_ONLY)
+                        wolfSSL_X509_NAME_free(dName);
+                    #endif /* OPENSSL_EXTRA */
                         return ASN_PARSE_E;
                 }
@@ -5922,172 +6140,42 @@
             XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen);
             idx += strLen;
-
-        #ifdef OPENSSL_EXTRA
-            if (count < DOMAIN_COMPONENT_MAX) {
-                /* store order that DN was parsed */
-                dName->loc[count++] = id;
-            }
-        #endif
-        }
+        }
+        #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+            !defined(WOLFCRYPT_ONLY)
+        switch (b) {
+            case CTC_UTF8:
+                enc = MBSTRING_UTF8;
+                break;
+            case CTC_PRINTABLE:
+                enc = V_ASN1_PRINTABLESTRING;
+                break;
+            default:
+                WOLFSSL_MSG("Unknown encoding type, using UTF8 by default");
+                enc = MBSTRING_UTF8;
+        }
+
+        if (nid != NID_undef) {
+            if (wolfSSL_X509_NAME_add_entry_by_NID(dName, nid, enc,
+                            &cert->source[cert->srcIdx], strLen, -1, -1) !=
+                            WOLFSSL_SUCCESS) {
+                wolfSSL_X509_NAME_free(dName);
+                return ASN_PARSE_E;
+            }
+        }
+        #endif /* OPENSSL_EXTRA */
         cert->srcIdx += strLen;
     }
     full[idx++] = 0;
-#if defined(OPENSSL_EXTRA)
-    /* store order that DN was parsed */
-    dName->locSz = count;
-#endif
-
-    #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
-    {
-        int totalLen = 0;
-        int i = 0;
-
-        if (dName->cnLen != 0)
-            totalLen += dName->cnLen + 4;
-        if (dName->snLen != 0)
-            totalLen += dName->snLen + 4;
-        if (dName->cLen != 0)
-            totalLen += dName->cLen + 3;
-        if (dName->lLen != 0)
-            totalLen += dName->lLen + 3;
-        if (dName->stLen != 0)
-            totalLen += dName->stLen + 4;
-        if (dName->oLen != 0)
-            totalLen += dName->oLen + 3;
-        if (dName->ouLen != 0)
-            totalLen += dName->ouLen + 4;
-        if (dName->emailLen != 0)
-            totalLen += dName->emailLen + 14;
-        if (dName->uidLen != 0)
-            totalLen += dName->uidLen + 5;
-        if (dName->serialLen != 0)
-            totalLen += dName->serialLen + 14;
-        if (dName->dcNum != 0){
-            for (i = 0;i < dName->dcNum;i++)
-                totalLen += dName->dcLen[i] + 4;
-        }
-
-        dName->fullName = (char*)XMALLOC(totalLen + 1, cert->heap,
-                                                             DYNAMIC_TYPE_X509);
-        if (dName->fullName != NULL) {
-            idx = 0;
-
-            if (dName->cnLen != 0) {
-                dName->entryCount++;
-                XMEMCPY(&dName->fullName[idx], WOLFSSL_COMMON_NAME, 4);
-                dName->cnNid = wc_OBJ_sn2nid((const char *)WOLFSSL_COMMON_NAME);
-                idx += 4;
-                XMEMCPY(&dName->fullName[idx],
-                                     &cert->source[dName->cnIdx], dName->cnLen);
-                dName->cnIdx = idx;
-                idx += dName->cnLen;
-            }
-            if (dName->snLen != 0) {
-                dName->entryCount++;
-                XMEMCPY(&dName->fullName[idx], WOLFSSL_SUR_NAME, 4);
-                dName->snNid = wc_OBJ_sn2nid((const char *)WOLFSSL_SUR_NAME);
-                idx += 4;
-                XMEMCPY(&dName->fullName[idx],
-                                     &cert->source[dName->snIdx], dName->snLen);
-                dName->snIdx = idx;
-                idx += dName->snLen;
-            }
-            if (dName->cLen != 0) {
-                dName->entryCount++;
-                XMEMCPY(&dName->fullName[idx], WOLFSSL_COUNTRY_NAME, 3);
-                dName->cNid = wc_OBJ_sn2nid((const char *)WOLFSSL_COUNTRY_NAME);
-                idx += 3;
-                XMEMCPY(&dName->fullName[idx],
-                                       &cert->source[dName->cIdx], dName->cLen);
-                dName->cIdx = idx;
-                idx += dName->cLen;
-            }
-            if (dName->lLen != 0) {
-                dName->entryCount++;
-                XMEMCPY(&dName->fullName[idx], WOLFSSL_LOCALITY_NAME, 3);
-                dName->lNid = wc_OBJ_sn2nid((const char *)WOLFSSL_LOCALITY_NAME);
-                idx += 3;
-                XMEMCPY(&dName->fullName[idx],
-                                       &cert->source[dName->lIdx], dName->lLen);
-                dName->lIdx = idx;
-                idx += dName->lLen;
-            }
-            if (dName->stLen != 0) {
-                dName->entryCount++;
-                XMEMCPY(&dName->fullName[idx], WOLFSSL_STATE_NAME, 4);
-                dName->stNid = wc_OBJ_sn2nid((const char *)WOLFSSL_STATE_NAME);
-                idx += 4;
-                XMEMCPY(&dName->fullName[idx],
-                                     &cert->source[dName->stIdx], dName->stLen);
-                dName->stIdx = idx;
-                idx += dName->stLen;
-            }
-            if (dName->oLen != 0) {
-                dName->entryCount++;
-                XMEMCPY(&dName->fullName[idx], WOLFSSL_ORG_NAME, 3);
-                dName->oNid = wc_OBJ_sn2nid((const char *)WOLFSSL_ORG_NAME);
-                idx += 3;
-                XMEMCPY(&dName->fullName[idx],
-                                       &cert->source[dName->oIdx], dName->oLen);
-                dName->oIdx = idx;
-                idx += dName->oLen;
-            }
-            if (dName->ouLen != 0) {
-                dName->entryCount++;
-                XMEMCPY(&dName->fullName[idx], WOLFSSL_ORGUNIT_NAME, 4);
-                dName->ouNid = wc_OBJ_sn2nid((const char *)WOLFSSL_ORGUNIT_NAME);
-                idx += 4;
-                XMEMCPY(&dName->fullName[idx],
-                                     &cert->source[dName->ouIdx], dName->ouLen);
-                dName->ouIdx = idx;
-                idx += dName->ouLen;
-            }
-            if (dName->emailLen != 0) {
-                dName->entryCount++;
-                XMEMCPY(&dName->fullName[idx], "/emailAddress=", 14);
-                dName->emailNid = wc_OBJ_sn2nid((const char *)"/emailAddress=");
-                idx += 14;
-                XMEMCPY(&dName->fullName[idx],
-                               &cert->source[dName->emailIdx], dName->emailLen);
-                dName->emailIdx = idx;
-                idx += dName->emailLen;
-            }
-            for (i = 0;i < dName->dcNum;i++){
-                if (dName->dcLen[i] != 0) {
-                    dName->entryCount++;
-                    XMEMCPY(&dName->fullName[idx], WOLFSSL_DOMAIN_COMPONENT, 4);
-                    idx += 4;
-                    XMEMCPY(&dName->fullName[idx],
-                                    &cert->source[dName->dcIdx[i]], dName->dcLen[i]);
-                    dName->dcIdx[i] = idx;
-                    idx += dName->dcLen[i];
-                }
-            }
-            if (dName->uidLen != 0) {
-                dName->entryCount++;
-                XMEMCPY(&dName->fullName[idx], "/UID=", 5);
-                dName->uidNid = wc_OBJ_sn2nid((const char *)"/UID=");
-                idx += 5;
-                XMEMCPY(&dName->fullName[idx],
-                                   &cert->source[dName->uidIdx], dName->uidLen);
-                dName->uidIdx = idx;
-                idx += dName->uidLen;
-            }
-            if (dName->serialLen != 0) {
-                dName->entryCount++;
-                XMEMCPY(&dName->fullName[idx], WOLFSSL_SERIAL_NUMBER, 14);
-                dName->serialNid = wc_OBJ_sn2nid((const char *)WOLFSSL_SERIAL_NUMBER);
-                idx += 14;
-                XMEMCPY(&dName->fullName[idx],
-                             &cert->source[dName->serialIdx], dName->serialLen);
-                dName->serialIdx = idx;
-                idx += dName->serialLen;
-            }
-            dName->fullName[idx] = '\0';
-            dName->fullNameLen = totalLen;
-        }
-    }
-    #endif /* OPENSSL_EXTRA */
-
+
+
+#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+            !defined(WOLFCRYPT_ONLY)
+    if (nameType == ISSUER) {
+        cert->issuerName = dName;
+    }
+    else {
+        cert->subjectName = dName;
+    }
+#endif
     return 0;
 }
@@ -6113,4 +6201,23 @@
     return 0;
 }
+
+#ifdef WOLFSSL_LINUXKM
+static WC_INLINE int GetTime_Long(long* value, const byte* date, int* idx)
+{
+    int i = *idx;
+
+    if (date[i] < 0x30 || date[i] > 0x39 || date[i+1] < 0x30 ||
+                                                             date[i+1] > 0x39) {
+        return ASN_PARSE_E;
+    }
+
+    *value += (long)btoi(date[i++]) * 10;
+    *value += (long)btoi(date[i++]);
+
+    *idx = i;
+
+    return 0;
+}
+#endif
 
 int ExtractDate(const unsigned char* date, unsigned char format,
@@ -6126,10 +6233,48 @@
     }
     else  { /* format == GENERALIZED_TIME */
+#ifdef WOLFSSL_LINUXKM
+        if (GetTime_Long(&certTime->tm_year, date, idx) != 0) return 0;
+#else
         if (GetTime(&certTime->tm_year, date, idx) != 0) return 0;
+#endif
         certTime->tm_year *= 100;
     }
 
+#ifdef AVR
+    /* Extract the time from the struct tm and adjust tm_year, tm_mon */
+    /* AVR libc stores these as uint8_t instead of int */
+    /* AVR time_t also offsets from midnight 1 Jan 2000 */
+    int tm_year = certTime->tm_year - 2000;
+    int tm_mon  = certTime->tm_mon - 1;
+    int tm_mday = certTime->tm_mday;
+    int tm_hour = certTime->tm_hour;
+    int tm_min  = certTime->tm_min;
+    int tm_sec  = certTime->tm_sec;
+
+#ifdef WOLFSSL_LINUXKM
+    if (GetTime_Long(&tm_year, date, idx) != 0) return 0;
+#else
+    if (GetTime(&tm_year, date, idx) != 0) return 0;
+#endif
+    if (GetTime(&tm_mon , date, idx) != 0) return 0;
+    if (GetTime(&tm_mday, date, idx) != 0) return 0;
+    if (GetTime(&tm_hour, date, idx) != 0) return 0;
+    if (GetTime(&tm_min , date, idx) != 0) return 0;
+    if (GetTime(&tm_sec , date, idx) != 0) return 0;
+
+    /* Re-populate certTime with computed values */
+    certTime->tm_year = tm_year;
+    certTime->tm_mon  = tm_mon;
+    certTime->tm_mday = tm_mday;
+    certTime->tm_hour = tm_hour;
+    certTime->tm_min  = tm_min;
+    certTime->tm_sec  = tm_sec;
+#else
     /* adjust tm_year, tm_mon */
+#ifdef WOLFSSL_LINUXKM
+    if (GetTime_Long(&certTime->tm_year, date, idx) != 0) return 0;
+#else
     if (GetTime(&certTime->tm_year, date, idx) != 0) return 0;
+#endif
     certTime->tm_year -= 1900;
     if (GetTime(&certTime->tm_mon , date, idx) != 0) return 0;
@@ -6139,4 +6284,5 @@
     if (GetTime(&certTime->tm_min , date, idx) != 0) return 0;
     if (GetTime(&certTime->tm_sec , date, idx) != 0) return 0;
+#endif
 
     return 1;
@@ -6182,5 +6328,5 @@
 
     XSNPRINTF(buf + idx, len - idx, "%2d %02d:%02d:%02d %d GMT",
-              t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, t.tm_year + 1900);
+              t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, (int)t.tm_year + 1900);
 
     return 1;
@@ -6199,4 +6345,7 @@
     struct tm* ts      = NULL;
     struct tm* tmpTime = NULL;
+    byte* data_ptr  = buf;
+    word32 data_len = 0;
+    int year, mon, day, hour, mini, sec;
 #if defined(NEED_TMP_TIME)
     struct tm tmpTimeStorage;
@@ -6205,7 +6354,4 @@
     (void)tmpTime;
 #endif
-    byte* data_ptr  = buf;
-    word32 data_len = 0;
-    int year, mon, day, hour, mini, sec;
 
     WOLFSSL_ENTER("SetAsnTimeString");
@@ -6320,5 +6466,5 @@
 /* like atoi but only use first byte */
 /* Make sure before and after dates are valid */
-int ValidateDate(const byte* date, byte format, int dateType)
+int wc_ValidateDate(const byte* date, byte format, int dateType)
 {
     time_t ltime;
@@ -6592,17 +6738,23 @@
     WOLFSSL_MSG("Got Cert Header");
 
-    /* Using the sigIndex as the upper bound because that's where the
-     * actual certificate data ends. */
-    if ( (ret = GetAlgoId(cert->source, &cert->srcIdx, &cert->signatureOID,
-                          oidSigType, cert->sigIndex)) < 0)
-        return ret;
-
-    WOLFSSL_MSG("Got Algo ID");
-
-    if ( (ret = GetName(cert, ISSUER, cert->sigIndex)) < 0)
-        return ret;
-
-    if ( (ret = GetValidity(cert, verify, cert->sigIndex)) < 0)
-        *badDate = ret;
+#ifdef WOLFSSL_CERT_REQ
+    if (!cert->isCSR) {
+#endif
+        /* Using the sigIndex as the upper bound because that's where the
+         * actual certificate data ends. */
+        if ( (ret = GetAlgoId(cert->source, &cert->srcIdx, &cert->signatureOID,
+                              oidSigType, cert->sigIndex)) < 0)
+            return ret;
+
+        WOLFSSL_MSG("Got Algo ID");
+
+        if ( (ret = GetName(cert, ISSUER, cert->sigIndex)) < 0)
+            return ret;
+
+        if ( (ret = GetValidity(cert, verify, cert->sigIndex)) < 0)
+            *badDate = ret;
+#ifdef WOLFSSL_CERT_REQ
+    }
+#endif
 
     if ( (ret = GetName(cert, SUBJECT, cert->sigIndex)) < 0)
@@ -6641,4 +6793,5 @@
     int length;
     int ret;
+
     ret = CheckBitString(cert->source, &cert->srcIdx, &length, cert->maxIdx, 1,
                          NULL);
@@ -6649,4 +6802,7 @@
     cert->signature = &cert->source[cert->srcIdx];
     cert->srcIdx += cert->sigLength;
+
+    if (cert->srcIdx != cert->maxIdx)
+        return ASN_PARSE_E;
 
     return 0;
@@ -6903,8 +7059,8 @@
         sigCtx->digest = NULL;
     }
-#ifndef NO_RSA
-    if (sigCtx->plain) {
-        XFREE(sigCtx->plain, sigCtx->heap, DYNAMIC_TYPE_SIGNATURE);
-        sigCtx->plain = NULL;
+#if !(defined(NO_RSA) && defined(NO_DSA))
+    if (sigCtx->sigCpy) {
+        XFREE(sigCtx->sigCpy, sigCtx->heap, DYNAMIC_TYPE_SIGNATURE);
+        sigCtx->sigCpy = NULL;
     }
 #endif
@@ -6918,4 +7074,10 @@
                 break;
         #endif /* !NO_RSA */
+        #ifndef NO_DSA
+            case DSAk:
+                wc_FreeDsaKey(sigCtx->key.dsa);
+                XFREE(sigCtx->key.dsa, sigCtx->heap, DYNAMIC_TYPE_DSA);
+                break;
+        #endif
         #ifdef HAVE_ECC
             case ECDSAk:
@@ -6998,4 +7160,5 @@
         case CTC_SHA256wRSA:
         case CTC_SHA256wECDSA:
+        case CTC_SHA256wDSA:
             if ((ret = wc_Sha256Hash(buf, bufSz, digest)) == 0) {
                 *typeH    = SHA256h;
@@ -7105,7 +7268,7 @@
                     sigCtx->key.rsa = (RsaKey*)XMALLOC(sizeof(RsaKey),
                                                 sigCtx->heap, DYNAMIC_TYPE_RSA);
-                    sigCtx->plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
+                    sigCtx->sigCpy = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ,
                                          sigCtx->heap, DYNAMIC_TYPE_SIGNATURE);
-                    if (sigCtx->key.rsa == NULL || sigCtx->plain == NULL) {
+                    if (sigCtx->key.rsa == NULL || sigCtx->sigCpy == NULL) {
                         ERROR_OUT(MEMORY_E, exit_cs);
                     }
@@ -7123,5 +7286,5 @@
                         goto exit_cs;
                     }
-                    XMEMCPY(sigCtx->plain, sig, sigSz);
+                    XMEMCPY(sigCtx->sigCpy, sig, sigSz);
                     sigCtx->out = NULL;
 
@@ -7132,4 +7295,63 @@
                 }
             #endif /* !NO_RSA */
+            #if !defined(NO_DSA) && !defined(HAVE_SELFTEST)
+                case DSAk:
+                {
+                    word32 idx = 0;
+
+                    if (sigSz < DSA_SIG_SIZE) {
+                        WOLFSSL_MSG("Verify Signature is too small");
+                        ERROR_OUT(BUFFER_E, exit_cs);
+                    }
+                    sigCtx->key.dsa = (DsaKey*)XMALLOC(sizeof(DsaKey),
+                                                sigCtx->heap, DYNAMIC_TYPE_DSA);
+                    sigCtx->sigCpy = (byte*)XMALLOC(sigSz,
+                                         sigCtx->heap, DYNAMIC_TYPE_SIGNATURE);
+                    if (sigCtx->key.dsa == NULL || sigCtx->sigCpy == NULL) {
+                        ERROR_OUT(MEMORY_E, exit_cs);
+                    }
+                    if ((ret = wc_InitDsaKey_h(sigCtx->key.dsa, sigCtx->heap)) != 0) {
+                        WOLFSSL_MSG("wc_InitDsaKey_h error");
+                        goto exit_cs;
+                    }
+                    if ((ret = wc_DsaPublicKeyDecode(key, &idx, sigCtx->key.dsa,
+                                                                 keySz)) != 0) {
+                        WOLFSSL_MSG("ASN Key decode error RSA");
+                        goto exit_cs;
+                    }
+                    if (sigSz != DSA_SIG_SIZE) {
+                #ifdef HAVE_ECC
+                        /* Try to parse it as the contents of a bitstring */
+                        mp_int r, s;
+                        idx = 0;
+                        if (DecodeECC_DSA_Sig(sig + idx, sigSz - idx,
+                                              &r, &s) != 0) {
+                            WOLFSSL_MSG("DSA Sig is in unrecognized or "
+                                        "incorrect format");
+                            ERROR_OUT(ASN_SIG_CONFIRM_E, exit_cs);
+                        }
+                        if (mp_to_unsigned_bin_len(&r, sigCtx->sigCpy,
+                                DSA_HALF_SIZE) != MP_OKAY ||
+                            mp_to_unsigned_bin_len(&s,
+                                    sigCtx->sigCpy + DSA_HALF_SIZE,
+                                    DSA_HALF_SIZE) != MP_OKAY) {
+                            WOLFSSL_MSG("DSA Sig is in unrecognized or "
+                                        "incorrect format");
+                            ERROR_OUT(ASN_SIG_CONFIRM_E, exit_cs);
+                        }
+                        mp_free(&r);
+                        mp_free(&s);
+                #else
+                        WOLFSSL_MSG("DSA Sig is in unrecognized or "
+                                    "incorrect format");
+                        ERROR_OUT(ASN_SIG_CONFIRM_E, exit_cs);
+                #endif
+                    }
+                    else {
+                        XMEMCPY(sigCtx->sigCpy, sig, DSA_SIG_SIZE);
+                    }
+                    break;
+                }
+            #endif /* !NO_DSA && !HAVE_SELFTEST */
             #ifdef HAVE_ECC
                 case ECDSAk:
@@ -7239,5 +7461,5 @@
                     if (sigCtx->pkCbRsa) {
                         ret = sigCtx->pkCbRsa(
-                                sigCtx->plain, sigSz, &sigCtx->out,
+                                sigCtx->sigCpy, sigSz, &sigCtx->out,
                                 key, keySz,
                                 sigCtx->pkCtxRsa);
@@ -7249,5 +7471,5 @@
                         if (rsaKeyIdx != NULL)
                         {
-                            ret = tsip_tls_CertVerify(buf, bufSz, sigCtx->plain,
+                            ret = tsip_tls_CertVerify(buf, bufSz, sigCtx->sigCpy,
                                 sigSz,
                                 sigCtx->pubkey_n_start - sigCtx->certBegin,
@@ -7266,5 +7488,5 @@
                         } else
                     #endif
-                        ret = wc_RsaSSL_VerifyInline(sigCtx->plain, sigSz,
+                        ret = wc_RsaSSL_VerifyInline(sigCtx->sigCpy, sigSz,
                                                  &sigCtx->out, sigCtx->key.rsa);
                     }
@@ -7272,4 +7494,12 @@
                 }
             #endif /* !NO_RSA */
+            #if !defined(NO_DSA) && !defined(HAVE_SELFTEST)
+                case DSAk:
+                {
+                    ret = wc_DsaVerify(sigCtx->digest, sigCtx->sigCpy,
+                            sigCtx->key.dsa, &sigCtx->verify);
+                    break;
+                }
+            #endif /* !NO_DSA && !HAVE_SELFTEST */
             #if defined(HAVE_ECC)
                 case ECDSAk:
@@ -7370,4 +7600,17 @@
                 }
             #endif /* NO_RSA */
+            #if !defined(NO_DSA) && !defined(HAVE_SELFTEST)
+                case DSAk:
+                {
+                    if (sigCtx->verify == 1) {
+                        ret = 0;
+                    }
+                    else {
+                        WOLFSSL_MSG("DSA Verify didn't match");
+                        ret = ASN_SIG_CONFIRM_E;
+                    }
+                    break;
+                }
+            #endif /* !NO_DSA && !HAVE_SELFTEST */
             #ifdef HAVE_ECC
                 case ECDSAk:
@@ -7547,4 +7790,23 @@
                         return 0;
                     }
+                    #ifndef WOLFSSL_NO_ASN_STRICT
+                    /* RFC 5280 section 4.2.1.10
+                       "Restrictions of the form directoryName MUST be
+                        applied to the subject field .... and to any names
+                        of type directoryName in the subjectAltName
+                        extension"
+                    */
+                    if (cert->altDirNames != NULL) {
+                        DNS_entry* cur = cert->altDirNames;
+                        while (cur != NULL) {
+                            if (XMEMCMP(cur->name, base->name, base->nameSz)
+                                    == 0) {
+                                WOLFSSL_MSG("DIR alt name constraint err");
+                                return 0;
+                            }
+                            cur = cur->next;
+                        }
+                    }
+                    #endif /* !WOLFSSL_NO_ASN_STRICT */
                     break;
                 }
@@ -7605,4 +7867,24 @@
                                                         base->nameSz) == 0) {
                         matchDir = 1;
+
+                        #ifndef WOLFSSL_NO_ASN_STRICT
+                        /* RFC 5280 section 4.2.1.10
+                           "Restrictions of the form directoryName MUST be
+                            applied to the subject field .... and to any names
+                            of type directoryName in the subjectAltName
+                            extension"
+                        */
+                        if (cert->altDirNames != NULL) {
+                            DNS_entry* cur = cert->altDirNames;
+                            while (cur != NULL) {
+                                if (XMEMCMP(cur->name, base->name, base->nameSz)
+                                        != 0) {
+                                    WOLFSSL_MSG("DIR alt name constraint err");
+                                    matchDir = 0; /* did not match */
+                                }
+                                cur = cur->next;
+                            }
+                        }
+                        #endif /* !WOLFSSL_NO_ASN_STRICT */
                     }
                     break;
@@ -7689,4 +7971,45 @@
         }
     #ifndef IGNORE_NAME_CONSTRAINTS
+        else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_DIR_TYPE)) {
+            DNS_entry* dirEntry;
+            int strLen;
+            word32 lenStartIdx = idx;
+
+            if (GetLength(input, &idx, &strLen, sz) < 0) {
+                WOLFSSL_MSG("\tfail: str length");
+                return ASN_PARSE_E;
+            }
+
+            if (GetSequence(input, &idx, &strLen, sz) < 0) {
+                WOLFSSL_MSG("\tfail: seq length");
+                return ASN_PARSE_E;
+            }
+            length -= (idx - lenStartIdx);
+
+            dirEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap,
+                                        DYNAMIC_TYPE_ALTNAME);
+            if (dirEntry == NULL) {
+                WOLFSSL_MSG("\tOut of Memory");
+                return MEMORY_E;
+            }
+
+            dirEntry->type = ASN_DIR_TYPE;
+            dirEntry->name = (char*)XMALLOC(strLen + 1, cert->heap,
+                                         DYNAMIC_TYPE_ALTNAME);
+            if (dirEntry->name == NULL) {
+                WOLFSSL_MSG("\tOut of Memory");
+                XFREE(dirEntry, cert->heap, DYNAMIC_TYPE_ALTNAME);
+                return MEMORY_E;
+            }
+            dirEntry->len = strLen;
+            XMEMCPY(dirEntry->name, &input[idx], strLen);
+            dirEntry->name[strLen] = '\0';
+
+            dirEntry->next = cert->altDirNames;
+            cert->altDirNames = dirEntry;
+
+            length -= strLen;
+            idx    += strLen;
+        }
         else if (b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE)) {
             DNS_entry* emailEntry;
@@ -7796,5 +8119,5 @@
             idx    += strLen;
         }
-#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL)
+#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_IP_ALT_NAME)
         else if (b == (ASN_CONTEXT_SPECIFIC | ASN_IP_TYPE)) {
             DNS_entry* ipAddr;
@@ -8396,5 +8719,8 @@
         }
 
-        DecodeSubtree(input + idx, length, subtree, cert->heap);
+        if (DecodeSubtree(input + idx, length, subtree, cert->heap) < 0) {
+            WOLFSSL_MSG("\terror parsing subtree");
+            return ASN_PARSE_E;
+        }
 
         idx += length;
@@ -8405,5 +8731,6 @@
 #endif /* IGNORE_NAME_CONSTRAINTS */
 
-#if (defined(WOLFSSL_CERT_EXT) && !defined(WOLFSSL_SEP)) || defined(OPENSSL_EXTRA)
+#if (defined(WOLFSSL_CERT_EXT) && !defined(WOLFSSL_SEP)) || \
+    defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
 
 /* Decode ITU-T X.690 OID format to a string representation
@@ -8597,16 +8924,21 @@
         return BAD_FUNC_ARG;
 
-    if (GetASNTag(input, &idx, &tag, sz) < 0) {
-        return ASN_PARSE_E;
-    }
-
-    if (tag != ASN_EXTENSIONS) {
-        WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
-        return ASN_PARSE_E;
-    }
-
-    if (GetLength(input, &idx, &length, sz) < 0) {
-        WOLFSSL_MSG("\tfail: invalid length");
-        return ASN_PARSE_E;
+#ifdef WOLFSSL_CERT_REQ
+    if (!cert->isCSR)
+#endif
+    { /* Not included in CSR */
+        if (GetASNTag(input, &idx, &tag, sz) < 0) {
+            return ASN_PARSE_E;
+        }
+
+        if (tag != ASN_EXTENSIONS) {
+            WOLFSSL_MSG("\tfail: should be an EXTENSIONS");
+            return ASN_PARSE_E;
+        }
+
+        if (GetLength(input, &idx, &length, sz) < 0) {
+            WOLFSSL_MSG("\tfail: invalid length");
+            return ASN_PARSE_E;
+        }
     }
 
@@ -8807,5 +9139,13 @@
                 break;
         #endif
-
+        #ifdef HAVE_OCSP
+            case OCSP_NOCHECK_OID:
+                VERIFY_AND_SET_OID(cert->ocspNoCheckSet);
+                ret = GetASNNull(input, &idx, sz);
+                length = 0; /* idx is already incremented, reset length to 0 */
+                if (ret != 0)
+                    return ASN_PARSE_E;
+                break;
+        #endif
             default:
             #ifndef WOLFSSL_NO_ASN_STRICT
@@ -8914,4 +9254,5 @@
  * in certificate signature verification.
  * Must use the signature OID from the signed part of the certificate.
+ * Works also on certificate signing requests.
  *
  * This is only for minimizing dynamic memory usage during TLS certificate
@@ -8921,5 +9262,5 @@
  */
 static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap,
-        void* cm, const byte* pubKey, word32 pubKeySz, int pubKeyOID)
+        void* cm, const byte* pubKey, word32 pubKeySz, int pubKeyOID, int req)
 {
 #ifndef WOLFSSL_SMALL_STACK
@@ -8998,5 +9339,6 @@
 
         /* signature */
-        if (GetAlgoId(cert, &idx, &signatureOID, oidSigType, certSz) < 0)
+        if (!req &&
+                GetAlgoId(cert, &idx, &signatureOID, oidSigType, certSz) < 0)
             ret = ASN_PARSE_E;
     }
@@ -9004,5 +9346,5 @@
     if (ret == 0) {
         issuerIdx = idx;
-        /* issuer */
+        /* issuer for cert or subject for csr */
         if (GetSequence(cert, &idx, &len, certSz) < 0)
             ret = ASN_PARSE_E;
@@ -9012,5 +9354,5 @@
     }
 #ifndef NO_SKID
-    if (ret == 0) {
+    if (!req && ret == 0) {
         idx += len;
 
@@ -9019,5 +9361,5 @@
             ret = ASN_PARSE_E;
     }
-    if (ret == 0) {
+    if (!req && ret == 0) {
         idx += len;
 
@@ -9033,120 +9375,134 @@
             ret = ASN_PARSE_E;
     }
-    if (ret == 0) {
+    if (req && ret == 0) {
         idx += len;
 
-        if ((idx + 1) > certSz)
-            ret = BUFFER_E;
-    }
-    if (ret == 0) {
-        /* issuerUniqueID - optional */
+        /* attributes */
+        if (GetASNHeader_ex(cert,
+                ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED, &idx,
+                &len, certSz, 1) < 0)
+            ret = ASN_PARSE_E;
+    }
+    if (!req) {
+        if (ret == 0) {
+            idx += len;
+
+            if ((idx + 1) > certSz)
+                ret = BUFFER_E;
+        }
+        if (ret == 0) {
+            /* issuerUniqueID - optional */
+            localIdx = idx;
+            if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
+                if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) {
+                    idx++;
+                    if (GetLength(cert, &idx, &len, certSz) < 0)
+                        ret = ASN_PARSE_E;
+                    idx += len;
+                }
+            }
+        }
+        if (ret == 0) {
+            if ((idx + 1) > certSz)
+                ret = BUFFER_E;
+        }
+        if (ret == 0) {
+            /* subjectUniqueID - optional */
+            localIdx = idx;
+            if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
+                if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)) {
+                    idx++;
+                    if (GetLength(cert, &idx, &len, certSz) < 0)
+                        ret = ASN_PARSE_E;
+                    idx += len;
+                }
+            }
+        }
+
+        if (ret == 0) {
+            if ((idx + 1) > certSz)
+                ret = BUFFER_E;
+        }
+        /* extensions - optional */
         localIdx = idx;
-        if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
-            if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) {
-                idx++;
-                if (GetLength(cert, &idx, &len, certSz) < 0)
+        if (ret == 0 && GetASNTag(cert, &localIdx, &tag, certSz) == 0 &&
+                tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 3)) {
+            idx++;
+            if (GetLength(cert, &idx, &extLen, certSz) < 0)
+                ret = ASN_PARSE_E;
+            if (ret == 0) {
+                if (GetSequence(cert, &idx, &extLen, certSz) < 0)
                     ret = ASN_PARSE_E;
-                idx += len;
-            }
-        }
-    }
-    if (ret == 0) {
-        if ((idx + 1) > certSz)
-            ret = BUFFER_E;
-    }
-    if (ret == 0) {
-        /* subjectUniqueID - optional */
-        localIdx = idx;
-        if (GetASNTag(cert, &localIdx, &tag, certSz) == 0) {
-            if (tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)) {
-                idx++;
-                if (GetLength(cert, &idx, &len, certSz) < 0)
-                    ret = ASN_PARSE_E;
-                idx += len;
-            }
-        }
-    }
-
-    if (ret == 0) {
-        if ((idx + 1) > certSz)
-            ret = BUFFER_E;
-    }
-    /* extensions - optional */
-    localIdx = idx;
-    if (ret == 0 && GetASNTag(cert, &localIdx, &tag, certSz) == 0 &&
-            tag == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 3)) {
-        idx++;
-        if (GetLength(cert, &idx, &extLen, certSz) < 0)
-            ret = ASN_PARSE_E;
-        if (ret == 0) {
-            if (GetSequence(cert, &idx, &extLen, certSz) < 0)
-                ret = ASN_PARSE_E;
-        }
-        if (ret == 0) {
-            extEndIdx = idx + extLen;
-
-            /* Check each extension for the ones we want. */
-            while (ret == 0 && idx < extEndIdx) {
-                if (GetSequence(cert, &idx, &len, certSz) < 0)
-                    ret = ASN_PARSE_E;
-                if (ret == 0) {
-                    extIdx = idx;
-                    if (GetObjectId(cert, &extIdx, &oid, oidCertExtType,
-                                                                  certSz) < 0) {
+            }
+            if (ret == 0) {
+                extEndIdx = idx + extLen;
+
+                /* Check each extension for the ones we want. */
+                while (ret == 0 && idx < extEndIdx) {
+                    if (GetSequence(cert, &idx, &len, certSz) < 0)
                         ret = ASN_PARSE_E;
+                    if (ret == 0) {
+                        extIdx = idx;
+                        if (GetObjectId(cert, &extIdx, &oid, oidCertExtType,
+                                                                      certSz) < 0) {
+                            ret = ASN_PARSE_E;
+                        }
+
+                        if (ret == 0) {
+                            if ((extIdx + 1) > certSz)
+                                ret = BUFFER_E;
+                        }
                     }
 
                     if (ret == 0) {
-                        if ((extIdx + 1) > certSz)
-                            ret = BUFFER_E;
+                        localIdx = extIdx;
+                        if (GetASNTag(cert, &localIdx, &tag, certSz) == 0 &&
+                                tag == ASN_BOOLEAN) {
+                            if (GetBoolean(cert, &extIdx, certSz) < 0)
+                                ret = ASN_PARSE_E;
+                        }
                     }
-                }
-
-                if (ret == 0) {
-                    localIdx = extIdx;
-                    if (GetASNTag(cert, &localIdx, &tag, certSz) == 0 &&
-                            tag == ASN_BOOLEAN) {
-                        if (GetBoolean(cert, &extIdx, certSz) < 0)
+                    if (ret == 0) {
+                        if (GetOctetString(cert, &extIdx, &extLen, certSz) < 0)
                             ret = ASN_PARSE_E;
                     }
-                }
-                if (ret == 0) {
-                    if (GetOctetString(cert, &extIdx, &extLen, certSz) < 0)
-                        ret = ASN_PARSE_E;
-                }
-
-                if (ret == 0) {
-                    switch (oid) {
-                    case AUTH_KEY_OID:
-                        if (GetSequence(cert, &extIdx, &extLen, certSz) < 0)
-                            ret = ASN_PARSE_E;
-
-                        if (ret == 0 && (extIdx + 1) >= certSz)
-                            ret = BUFFER_E;
-
-                        if (ret == 0 &&
-                                GetASNTag(cert, &extIdx, &tag, certSz) == 0 &&
-                                tag == (ASN_CONTEXT_SPECIFIC | 0)) {
-                            if (GetLength(cert, &extIdx, &extLen, certSz) <= 0)
+
+                    if (ret == 0) {
+                        switch (oid) {
+                        case AUTH_KEY_OID:
+                            if (GetSequence(cert, &extIdx, &extLen, certSz) < 0)
                                 ret = ASN_PARSE_E;
-                            if (ret == 0) {
-                                extAuthKeyIdSet = 1;
-                                if (extLen == KEYID_SIZE)
-                                    XMEMCPY(hash, cert + extIdx, extLen);
-                                else {
-                                    ret = CalcHashId(cert + extIdx, extLen,
-                                                                          hash);
+
+                            if (ret == 0 && (extIdx + 1) >= certSz)
+                                ret = BUFFER_E;
+
+                            if (ret == 0 &&
+                                    GetASNTag(cert, &extIdx, &tag, certSz) == 0 &&
+                                    tag == (ASN_CONTEXT_SPECIFIC | 0)) {
+                                if (GetLength(cert, &extIdx, &extLen, certSz) <= 0)
+                                    ret = ASN_PARSE_E;
+                                if (ret == 0) {
+                                    extAuthKeyIdSet = 1;
+                                    if (extLen == KEYID_SIZE)
+                                        XMEMCPY(hash, cert + extIdx, extLen);
+                                    else {
+                                        ret = CalcHashId(cert + extIdx, extLen,
+                                                                              hash);
+                                    }
                                 }
                             }
+                            break;
+
+                        default:
+                            break;
                         }
-                        break;
-
-                    default:
-                        break;
                     }
+                    idx += len;
                 }
-                idx += len;
-            }
-        }
+            }
+        }
+    }
+    else if (ret == 0) {
+        idx += len;
     }
 
@@ -9175,4 +9531,7 @@
         if (GetAlgoId(cert, &idx, &oid, oidSigType, certSz) < 0)
             ret = ASN_PARSE_E;
+        /* In CSR signature data is not present in body */
+        if (req)
+            signatureOID = oid;
     }
     if (ret == 0) {
@@ -9219,6 +9578,14 @@
 {
     return CheckCertSignature_ex(cert, certSz, heap, NULL,
-            pubKey, pubKeySz, pubKeyOID);
-}
+            pubKey, pubKeySz, pubKeyOID, 0);
+}
+#ifdef WOLFSSL_CERT_REQ
+int CheckCSRSignaturePubKey(const byte* cert, word32 certSz, void* heap,
+        const byte* pubKey, word32 pubKeySz, int pubKeyOID)
+{
+    return CheckCertSignature_ex(cert, certSz, heap, NULL,
+            pubKey, pubKeySz, pubKeyOID, 1);
+}
+#endif /* WOLFSSL_CERT_REQ */
 #endif /* OPENSSL_EXTRA */
 #ifdef WOLFSSL_SMALL_CERT_VERIFY
@@ -9227,5 +9594,5 @@
 int CheckCertSignature(const byte* cert, word32 certSz, void* heap, void* cm)
 {
-    return CheckCertSignature_ex(cert, certSz, heap, cm, NULL, 0, 0);
+    return CheckCertSignature_ex(cert, certSz, heap, cm, NULL, 0, 0, 0);
 }
 #endif /* WOLFSSL_SMALL_CERT_VERIFY */
@@ -9237,13 +9604,21 @@
     int    checkPathLen = 0;
     int    decrementMaxPathLen = 0;
-    word32 confirmOID;
+    word32 confirmOID = 0;
 #if defined(WOLFSSL_RENESAS_TSIP)
     int    idx = 0;
 #endif
     byte*  tsip_encRsaKeyIdx;
+#ifdef WOLFSSL_CERT_REQ
+    int    len = 0;
+#endif
 
     if (cert == NULL) {
         return BAD_FUNC_ARG;
     }
+
+#ifdef WOLFSSL_CERT_REQ
+    if (type == CERTREQ_TYPE)
+        cert->isCSR = 1;
+#endif
 
     if (cert->sigCtx.state == SIG_STATE_BEGIN) {
@@ -9259,4 +9634,101 @@
         WOLFSSL_MSG("Parsed Past Key");
 
+
+#ifdef WOLFSSL_CERT_REQ
+        /* Read attributes */
+        if (cert->isCSR) {
+            if (GetASNHeader_ex(cert->source,
+                    ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED, &cert->srcIdx,
+                    &len, cert->maxIdx, 1) < 0) {
+                WOLFSSL_MSG("GetASNHeader_ex error");
+                return ASN_PARSE_E;
+            }
+
+            if (len) {
+                word32 attrMaxIdx = cert->srcIdx + len;
+                word32 oid;
+                byte   tag;
+
+                if (attrMaxIdx > cert->maxIdx) {
+                    WOLFSSL_MSG("Attribute length greater than CSR length");
+                    return ASN_PARSE_E;
+                }
+
+                while (cert->srcIdx < attrMaxIdx) {
+                    /* Attributes have the structure:
+                     * SEQ -> OID -> SET -> ATTRIBUTE */
+                    if (GetSequence(cert->source, &cert->srcIdx, &len,
+                            attrMaxIdx) < 0) {
+                        WOLFSSL_MSG("attr GetSequence error");
+                        return ASN_PARSE_E;
+                    }
+                    if (GetObjectId(cert->source, &cert->srcIdx, &oid,
+                            oidCsrAttrType, attrMaxIdx) < 0) {
+                        WOLFSSL_MSG("attr GetObjectId error");
+                        return ASN_PARSE_E;
+                    }
+                    if (GetSet(cert->source, &cert->srcIdx, &len,
+                            attrMaxIdx) < 0) {
+                        WOLFSSL_MSG("attr GetSet error");
+                        return ASN_PARSE_E;
+                    }
+                    switch (oid) {
+                    case CHALLENGE_PASSWORD_OID:
+                        if (GetHeader(cert->source, &tag,
+                                &cert->srcIdx, &len, attrMaxIdx, 1) < 0) {
+                            WOLFSSL_MSG("attr GetHeader error");
+                            return ASN_PARSE_E;
+                        }
+                        if (tag != ASN_PRINTABLE_STRING && tag != ASN_UTF8STRING &&
+                                tag != ASN_IA5_STRING) {
+                            WOLFSSL_MSG("Unsupported attribute value format");
+                            return ASN_PARSE_E;
+                        }
+                        cert->cPwd = (char*)cert->source + cert->srcIdx;
+                        cert->cPwdLen = len;
+                        cert->srcIdx += len;
+                        break;
+                    case SERIAL_NUMBER_OID:
+                        if (GetHeader(cert->source, &tag,
+                                &cert->srcIdx, &len, attrMaxIdx, 1) < 0) {
+                            WOLFSSL_MSG("attr GetHeader error");
+                            return ASN_PARSE_E;
+                        }
+                        if (tag != ASN_PRINTABLE_STRING && tag != ASN_UTF8STRING &&
+                                tag != ASN_IA5_STRING) {
+                            WOLFSSL_MSG("Unsupported attribute value format");
+                            return ASN_PARSE_E;
+                        }
+                        cert->sNum = (char*)cert->source + cert->srcIdx;
+                        cert->sNumLen = len;
+                        cert->srcIdx += len;
+                        if (cert->sNumLen <= EXTERNAL_SERIAL_SIZE) {
+                            XMEMCPY(cert->serial, cert->sNum, cert->sNumLen);
+                            cert->serialSz = cert->sNumLen;
+                        }
+                        break;
+                    case EXTENSION_REQUEST_OID:
+                        /* save extensions */
+                        cert->extensions    = &cert->source[cert->srcIdx];
+                        cert->extensionsSz  = len;
+                        cert->extensionsIdx = cert->srcIdx;   /* for potential later use */
+
+                        if ((ret = DecodeCertExtensions(cert)) < 0) {
+                            if (ret == ASN_CRIT_EXT_E)
+                                cert->criticalExt = ret;
+                            else
+                                return ret;
+                        }
+                        cert->srcIdx += len;
+                        break;
+                    default:
+                        WOLFSSL_MSG("Unsupported attribute type");
+                        return ASN_PARSE_E;
+                    }
+                }
+            }
+        }
+#endif
+
         if (cert->srcIdx < cert->sigIndex) {
         #ifndef ALLOW_V1_EXTENSIONS
@@ -9279,10 +9751,20 @@
             }
 
+        #ifdef HAVE_OCSP
+            /* trust for the lifetime of the responder's cert*/
+            if (cert->ocspNoCheckSet && verify == VERIFY_OCSP)
+                verify = NO_VERIFY;
+        #endif
             /* advance past extensions */
             cert->srcIdx = cert->sigIndex;
         }
 
-        if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID,
-                             oidSigType, cert->maxIdx)) < 0)
+        if ((ret = GetAlgoId(cert->source, &cert->srcIdx,
+#ifdef WOLFSSL_CERT_REQ
+                !cert->isCSR ? &confirmOID : &cert->signatureOID,
+#else
+                &confirmOID,
+#endif
+                oidSigType, cert->maxIdx)) < 0)
             return ret;
 
@@ -9290,5 +9772,9 @@
             return ret;
 
-        if (confirmOID != cert->signatureOID)
+        if (confirmOID != cert->signatureOID
+#ifdef WOLFSSL_CERT_REQ
+                && !cert->isCSR
+#endif
+                )
             return ASN_SIG_OID_E;
 
@@ -9341,4 +9827,8 @@
             cert->ca = GetCA(cm, cert->issuerHash);
     #endif /* !NO_SKID */
+
+            if (cert->ca) {
+                WOLFSSL_MSG("CA found");
+            }
         }
 
@@ -9425,16 +9915,16 @@
                 }
             }
-            #ifdef HAVE_OCSP
-            if (verify != NO_VERIFY && type != CA_TYPE &&
-                                                    type != TRUSTED_PEER_TYPE) {
-                if (cert->ca) {
-                    /* Need the CA's public key hash for OCSP */
-                    XMEMCPY(cert->issuerKeyHash, cert->ca->subjectKeyHash,
-                                                                    KEYID_SIZE);
-                }
-
-            }
-            #endif /* HAVE_OCSP */
-        }
+        }
+
+        #ifdef HAVE_OCSP
+        if (verify != NO_VERIFY && type != CA_TYPE &&
+                                                type != TRUSTED_PEER_TYPE) {
+            if (cert->ca) {
+                /* Need the CA's public key hash for OCSP */
+                XMEMCPY(cert->issuerKeyHash, cert->ca->subjectKeyHash,
+                                                                KEYID_SIZE);
+            }
+        }
+        #endif /* HAVE_OCSP */
     }
 #if defined(WOLFSSL_RENESAS_TSIP)
@@ -9799,7 +10289,7 @@
 #if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)
 
-/* Max X509 header length indicates the max length + 2 ('\n', '\0') */
-#define MAX_X509_HEADER_SZ  (37 + 2)
-
+/* Note: If items added make sure MAX_X509_HEADER_SZ is 
+    updated to reflect maximum length and pem_struct_min_sz
+    to reflect minimum size */
 wcchar BEGIN_CERT           = "-----BEGIN CERTIFICATE-----";
 wcchar END_CERT             = "-----END CERTIFICATE-----";
@@ -9844,9 +10334,7 @@
     wcchar END_EDDSA_PRIV   = "-----END EDDSA PRIVATE KEY-----";
 #endif
-#ifdef HAVE_CRL
-    const char *const BEGIN_CRL = "-----BEGIN X509 CRL-----";
-    wcchar END_CRL   = "-----END X509 CRL-----";
-#endif
-
+
+const int pem_struct_min_sz = XSTR_SIZEOF("-----BEGIN X509 CRL-----"
+                                             "-----END X509 CRL-----");
 
 static WC_INLINE char* SkipEndOfLineChars(char* line, const char* endOfLine)
@@ -9940,5 +10428,5 @@
             ret = 0;
             break;
-    #if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL))
+    #ifndef NO_DH
         case DH_PRIVATEKEY_TYPE:
     #endif
@@ -10374,6 +10862,6 @@
         } else
 #ifdef HAVE_CRL
-        if ((type == CRL_TYPE) && (header != BEGIN_CRL)) {
-            header =  BEGIN_CRL;                footer = END_CRL;
+        if ((type == CRL_TYPE) && (header != BEGIN_X509_CRL)) {
+            header =  BEGIN_X509_CRL;           footer = END_X509_CRL;
         } else
 #endif
@@ -10385,46 +10873,63 @@
     if (!headerEnd) {
 #ifdef OPENSSL_EXTRA
-        char* beginEnd;
-        int endLen;
-        /* see if there is a -----BEGIN * PRIVATE KEY----- header */
-        headerEnd = XSTRNSTR((char*)buff, PRIV_KEY_SUFFIX, sz);
-        if (headerEnd) {
-            beginEnd = headerEnd + XSTR_SIZEOF(PRIV_KEY_SUFFIX);
-            /* back up to BEGIN_PRIV_KEY_PREFIX */
-            headerEnd -= XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX);
-            while (headerEnd > (char*)buff &&
-                    XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX,
-                            XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0) {
-                headerEnd--;
-            }
-            if (headerEnd <= (char*)buff ||
-                    XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX,
-                    XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0 ||
-                    beginEnd - headerEnd > PEM_LINE_LEN) {
-                WOLFSSL_MSG("Couldn't find PEM header");
-                return ASN_NO_PEM_HEADER;
-            }
-            /* headerEnd now points to beginning of header */
-            XMEMCPY(beginBuf, headerEnd, beginEnd - headerEnd);
-            beginBuf[beginEnd - headerEnd] = '\0';
-            /* look for matching footer */
-            footer = XSTRNSTR(beginEnd,
-                            beginBuf + XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX),
-                            (unsigned int)((char*)buff + sz - beginEnd));
-            if (!footer) {
-                WOLFSSL_MSG("Couldn't find PEM footer");
-                return ASN_NO_PEM_HEADER;
-            }
-            footer -= XSTR_SIZEOF(END_PRIV_KEY_PREFIX);
-            endLen = (unsigned int)(beginEnd - headerEnd -
-                        (XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX) -
-                                XSTR_SIZEOF(END_PRIV_KEY_PREFIX)));
-            XMEMCPY(endBuf, footer, endLen);
-            endBuf[endLen] = '\0';
-
-            header = beginBuf;
-            footer = endBuf;
-            headerEnd = beginEnd;
-        } else {
+        if (type == PRIVATEKEY_TYPE) {
+            char* beginEnd;
+            int endLen;
+            /* see if there is a -----BEGIN * PRIVATE KEY----- header */
+            headerEnd = XSTRNSTR((char*)buff, PRIV_KEY_SUFFIX, sz);
+            if (headerEnd) {
+                beginEnd = headerEnd + XSTR_SIZEOF(PRIV_KEY_SUFFIX);
+                if (beginEnd >= (char*)buff + sz) {
+                    return BUFFER_E;
+                }
+
+                /* back up to BEGIN_PRIV_KEY_PREFIX */
+                while (headerEnd > (char*)buff &&
+                        XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX,
+                                XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0 &&
+                        *headerEnd != '\n') {
+                    headerEnd--;
+                }
+                if (headerEnd <= (char*)buff ||
+                        XSTRNCMP(headerEnd, BEGIN_PRIV_KEY_PREFIX,
+                        XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX)) != 0 ||
+                        beginEnd - headerEnd > PEM_LINE_LEN) {
+                    WOLFSSL_MSG("Couldn't find PEM header");
+                    return ASN_NO_PEM_HEADER;
+                }
+
+                /* headerEnd now points to beginning of header */
+                XMEMCPY(beginBuf, headerEnd, beginEnd - headerEnd);
+                beginBuf[beginEnd - headerEnd] = '\0';
+                /* look for matching footer */
+                footer = XSTRNSTR(beginEnd,
+                                beginBuf + XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX),
+                                (unsigned int)((char*)buff + sz - beginEnd));
+                if (!footer) {
+                    WOLFSSL_MSG("Couldn't find PEM footer");
+                    return ASN_NO_PEM_HEADER;
+                }
+
+                footer -= XSTR_SIZEOF(END_PRIV_KEY_PREFIX);
+                if (footer > (char*)buff + sz - XSTR_SIZEOF(END_PRIV_KEY_PREFIX)
+                        || XSTRNCMP(footer, END_PRIV_KEY_PREFIX,
+                            XSTR_SIZEOF(END_PRIV_KEY_PREFIX)) != 0) {
+                    WOLFSSL_MSG("Unexpected footer for PEM");
+                    return BUFFER_E;
+                }
+
+                endLen = (unsigned int)(beginEnd - headerEnd -
+                            (XSTR_SIZEOF(BEGIN_PRIV_KEY_PREFIX) -
+                                    XSTR_SIZEOF(END_PRIV_KEY_PREFIX)));
+                XMEMCPY(endBuf, footer, endLen);
+                endBuf[endLen] = '\0';
+
+                header = beginBuf;
+                footer = endBuf;
+                headerEnd = beginEnd;
+            }
+        }
+
+        if (!headerEnd) {
             WOLFSSL_MSG("Couldn't find PEM header");
             return ASN_NO_PEM_HEADER;
@@ -10583,7 +11088,21 @@
                 #ifndef NO_DES3
                     if (info->cipherType == WC_CIPHER_DES3) {
-                        padVal = der->buffer[der->length-1];
-                        if (padVal <= DES_BLOCK_SIZE) {
-                            der->length -= padVal;
+                        /* Assuming there is padding:
+                         *      (der->length > 0 && der->length > DES_BLOCK_SIZE &&
+                         *       (der->length % DES_BLOCK_SIZE) != 0)
+                         * and assuming the last value signifies the number of
+                         * padded bytes IE if last value is 0x08 then there are
+                         * 8 bytes of padding:
+                         *      padVal = der->buffer[der->length-1];
+                         * then strip this padding before proceeding:
+                         * der->length -= padVal;
+                         */
+                        if (der->length > 0 &&
+                            der->length > DES_BLOCK_SIZE &&
+                            (der->length % DES_BLOCK_SIZE) != 0) {
+                            padVal = der->buffer[der->length-1];
+                            if (padVal < DES_BLOCK_SIZE) {
+                                der->length -= padVal;
+                            }
                         }
                     }
@@ -10822,5 +11341,5 @@
 
         if (ret == 0) {
-            if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) {
+            if ((size_t)XFREAD(fileBuf, 1, sz, file) != (size_t)sz) {
                 ret = BUFFER_E;
             }
@@ -10902,5 +11421,5 @@
         }
         if (ret == 0) {
-            if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) {
+            if ((size_t)XFREAD(fileBuf, 1, sz, file) != (size_t)sz) {
                 ret = BUFFER_E;
             }
@@ -11477,5 +11996,5 @@
 #endif
 
-#ifdef HAVE_SELFTEST
+#if defined(HAVE_SELFTEST) || defined(HAVE_FIPS)
     /* older version of ecc.c can not handle dp being NULL */
     if (key != NULL && key->dp == NULL) {
@@ -11584,5 +12103,5 @@
     }
 
-#ifdef HAVE_SELFTEST
+#if defined(HAVE_SELFTEST) || defined(HAVE_FIPS)
     /* older version of ecc.c can not handle dp being NULL */
     if (key != NULL && key->dp == NULL) {
@@ -11648,5 +12167,5 @@
     if (idx != 0) {
 #ifdef WOLFSSL_SMALL_STACK
-        XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
 #endif
         return idx;
@@ -11658,5 +12177,5 @@
         algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
         if (algo == NULL) {
-            XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
             return MEMORY_E;
         }
@@ -11752,5 +12271,5 @@
     if (idx != 0) {
 #ifdef WOLFSSL_SMALL_STACK
-        XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
 #endif
         return idx;
@@ -11762,5 +12281,5 @@
         algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
         if (algo == NULL) {
-            XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+            XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER);
             return MEMORY_E;
         }
@@ -11887,81 +12406,4 @@
 
 #endif
-
-
-/* Set Date validity from now until now + daysValid
- * return size in bytes written to output, 0 on error */
-static int SetValidity(byte* output, int daysValid)
-{
-    byte before[MAX_DATE_SIZE];
-    byte  after[MAX_DATE_SIZE];
-
-    int beforeSz;
-    int afterSz;
-    int seqSz;
-
-    time_t now;
-    time_t then;
-    struct tm* tmpTime;
-    struct tm* expandedTime;
-    struct tm localTime;
-
-#if defined(NEED_TMP_TIME)
-    /* for use with gmtime_r */
-    struct tm tmpTimeStorage;
-    tmpTime = &tmpTimeStorage;
-#else
-    tmpTime = NULL;
-#endif
-    (void)tmpTime;
-
-    now = XTIME(0);
-
-    /* before now */
-    before[0] = ASN_GENERALIZED_TIME;
-    beforeSz = SetLength(ASN_GEN_TIME_SZ, before + 1) + 1;  /* gen tag */
-
-    /* subtract 1 day of seconds for more compliance */
-    then = now - 86400;
-    expandedTime = XGMTIME(&then, tmpTime);
-    if (expandedTime == NULL) {
-        WOLFSSL_MSG("XGMTIME failed");
-        return 0;   /* error */
-    }
-    localTime = *expandedTime;
-
-    /* adjust */
-    localTime.tm_year += 1900;
-    localTime.tm_mon +=    1;
-
-    SetTime(&localTime, before + beforeSz);
-    beforeSz += ASN_GEN_TIME_SZ;
-
-    after[0] = ASN_GENERALIZED_TIME;
-    afterSz  = SetLength(ASN_GEN_TIME_SZ, after + 1) + 1;  /* gen tag */
-
-    /* add daysValid of seconds */
-    then = now + (daysValid * (time_t)86400);
-    expandedTime = XGMTIME(&then, tmpTime);
-    if (expandedTime == NULL) {
-        WOLFSSL_MSG("XGMTIME failed");
-        return 0;   /* error */
-    }
-    localTime = *expandedTime;
-
-    /* adjust */
-    localTime.tm_year += 1900;
-    localTime.tm_mon  +=    1;
-
-    SetTime(&localTime, after + afterSz);
-    afterSz += ASN_GEN_TIME_SZ;
-
-    /* headers and output */
-    seqSz = SetSequence(beforeSz + afterSz, output);
-    XMEMCPY(output + seqSz, before, beforeSz);
-    XMEMCPY(output + seqSz + beforeSz, after, afterSz);
-
-    return seqSz + beforeSz + afterSz;
-}
-
 
 /* ASN Encoded Name field */
@@ -11976,5 +12418,5 @@
 
 /* Get Which Name from index */
-static const char* GetOneName(CertName* name, int idx)
+const char* GetOneCertName(CertName* name, int idx)
 {
     switch (idx) {
@@ -12065,5 +12507,5 @@
 
 /* Get ASN Name from index */
-static byte GetNameId(int idx)
+byte GetCertNameId(int idx)
 {
     switch (idx) {
@@ -12106,4 +12548,5 @@
     }
 }
+
 
 /*
@@ -12528,5 +12971,9 @@
     curName = names;
     do {
-        output[idx++] = ASN_CONTEXT_SPECIFIC | curName->type;
+        output[idx] = ASN_CONTEXT_SPECIFIC | curName->type;
+        if (curName->type == ASN_DIR_TYPE) {
+            output[idx] |= ASN_CONSTRUCTED;
+        }
+        idx++;
         idx += SetLength(curName->len, output + idx);
         XMEMCPY(output + idx, curName->name, curName->len);
@@ -12574,4 +13021,5 @@
         /* Restrict country code size */
         if (ASN_COUNTRY_NAME == type && strLen != CTC_COUNTRY_SIZE) {
+            WOLFSSL_MSG("Country code size error");
             return ASN_COUNTRY_SIZE_E;
         }
@@ -12671,4 +13119,159 @@
 }
 
+
+
+
+/* Guarded by either
+ * A) WOLFSSL_WPAS_SMALL is on or
+ * B) (OPENSSL_EXTRA or OPENSSL_EXTRA_X509_SMALL) + WOLFSSL_CERT_GEN +
+ *    (WOLFSSL_CERT_REQ or WOLFSSL_CERT_EXT or OPENSSL_EXTRA) has been
+ *    defined
+ */
+#if defined(WOLFSSL_WPAS_SMALL) || \
+    (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
+    defined(WOLFSSL_CERT_GEN) && \
+    (defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT) || \
+     defined(OPENSSL_EXTRA))
+/* Converts from NID_* value to wolfSSL value if needed */
+static int ConvertNIDToWolfSSL(int nid)
+{
+    switch (nid) {
+        case NID_commonName : return ASN_COMMON_NAME;
+        case NID_surname :    return ASN_SUR_NAME;
+        case NID_countryName: return ASN_COUNTRY_NAME;
+        case NID_localityName: return ASN_LOCALITY_NAME;
+        case NID_stateOrProvinceName: return ASN_STATE_NAME;
+        case NID_organizationName: return ASN_ORG_NAME;
+        case NID_organizationalUnitName: return ASN_ORGUNIT_NAME;
+        case NID_emailAddress: return ASN_EMAIL_NAME;
+        case NID_serialNumber: return ASN_SERIAL_NUMBER;
+        case NID_businessCategory: return ASN_BUS_CAT;
+        case NID_domainComponent: return ASN_DOMAIN_COMPONENT;
+        default:
+            WOLFSSL_MSG("Attribute NID not found");
+            return -1;
+    }
+}
+
+
+/* Converts the x509 name structure into DER format.
+ *
+ * out  pointer to either a pre setup buffer or a pointer to null for
+ *      creating a dynamic buffer. In the case that a pre-existing buffer is
+ *      used out will be incremented the size of the DER buffer on success.
+ *
+ * returns the size of the buffer on success, or negative value with failure
+ */
+int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out)
+{
+    int  totalBytes = 0, i, idx;
+    byte temp[MAX_SEQ_SZ];
+    byte *output, *local = NULL;
+#ifdef WOLFSSL_SMALL_STACK
+    EncodedName* names = NULL;
+#else
+    EncodedName  names[MAX_NAME_ENTRIES];
+#endif
+
+    if (out == NULL || name == NULL)
+        return BAD_FUNC_ARG;
+
+#ifdef WOLFSSL_SMALL_STACK
+    names = (EncodedName*)XMALLOC(sizeof(EncodedName) * MAX_NAME_ENTRIES, NULL,
+                                                       DYNAMIC_TYPE_TMP_BUFFER);
+    if (names == NULL)
+        return MEMORY_E;
+#endif
+
+    XMEMSET(names, 0, sizeof(EncodedName) * MAX_NAME_ENTRIES);
+
+    for (i = 0; i < MAX_NAME_ENTRIES; i++) {
+        WOLFSSL_X509_NAME_ENTRY* entry;
+        int ret;
+
+        entry = wolfSSL_X509_NAME_get_entry(name, i);
+        if (entry != NULL && entry->set == 1) {
+            const char* nameStr;
+            int type;
+            WOLFSSL_ASN1_STRING* data;
+
+            data = wolfSSL_X509_NAME_ENTRY_get_data(entry);
+            if (data == NULL) {
+            #ifdef WOLFSSL_SMALL_STACK
+                XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            #endif
+                WOLFSSL_MSG("Error getting entry data");
+                return WOLFSSL_FATAL_ERROR;
+            }
+
+            nameStr = (const char*)wolfSSL_ASN1_STRING_data(data);
+            type    = wolfSSL_ASN1_STRING_type(data);
+
+            switch (type) {
+                case MBSTRING_UTF8:
+                    type = CTC_UTF8;
+                    break;
+                case V_ASN1_PRINTABLESTRING:
+                    type = CTC_PRINTABLE;
+                    break;
+                default:
+                    WOLFSSL_MSG("Unknown encoding type conversion UTF8 by default");
+                    type = CTC_UTF8;
+            }
+            ret = wc_EncodeName(&names[i], nameStr, type,
+                ConvertNIDToWolfSSL(entry->nid));
+            if (ret < 0) {
+            #ifdef WOLFSSL_SMALL_STACK
+                XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            #endif
+                WOLFSSL_MSG("EncodeName failed");
+                return WOLFSSL_FATAL_ERROR;
+            }
+            totalBytes += ret;
+        }
+    }
+
+    /* header */
+    idx = SetSequence(totalBytes, temp);
+    if (totalBytes + idx > ASN_NAME_MAX) {
+#ifdef WOLFSSL_SMALL_STACK
+        XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+        WOLFSSL_MSG("Total Bytes is greater than ASN_NAME_MAX");
+        return BUFFER_E;
+    }
+
+    /* check if using buffer passed in */
+    if (*out == NULL) {
+        *out = local = (unsigned char*)XMALLOC(totalBytes + idx, NULL,
+                DYNAMIC_TYPE_OPENSSL);
+        if (*out == NULL) {
+            return MEMORY_E;
+        }
+    }
+    output = *out;
+
+    idx = SetSequence(totalBytes, output);
+    totalBytes += idx;
+    for (i = 0; i < MAX_NAME_ENTRIES; i++) {
+        if (names[i].used) {
+            XMEMCPY(output + idx, names[i].encoded, names[i].totalLen);
+            idx += names[i].totalLen;
+        }
+    }
+
+#ifdef WOLFSSL_SMALL_STACK
+    XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
+
+    /* used existing buffer passed in, so increment pointer */
+    if (local == NULL) {
+        *out += totalBytes;
+    }
+    return totalBytes;
+}
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
+
+
 /* encode CertName into output, return total bytes written */
 int SetName(byte* output, word32 outputSz, CertName* name)
@@ -12700,13 +13303,14 @@
     for (i = 0; i < NAME_ENTRIES; i++) {
         int ret;
-        const char* nameStr = GetOneName(name, i);
+        const char* nameStr = GetOneCertName(name, i);
 
         ret = wc_EncodeName(&names[i], nameStr, GetNameType(name, i),
-                          GetNameId(i));
+                          GetCertNameId(i));
         if (ret < 0) {
         #ifdef WOLFSSL_SMALL_STACK
-                XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+            XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
         #endif
-                return BUFFER_E;
+            WOLFSSL_MSG("EncodeName failed");
+            return BUFFER_E;
         }
         totalBytes += ret;
@@ -12722,4 +13326,5 @@
                 XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
             #endif
+                WOLFSSL_MSG("EncodeName on multiple attributes failed\n");
                 return BUFFER_E;
             }
@@ -12739,4 +13344,5 @@
         XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
 #endif
+        WOLFSSL_MSG("Total Bytes is greater than ASN_NAME_MAX");
         return BUFFER_E;
     }
@@ -12744,5 +13350,5 @@
     for (i = 0; i < NAME_ENTRIES; i++) {
     #ifdef WOLFSSL_MULTI_ATTRIB
-        type = GetNameId(i);
+        type = GetCertNameId(i);
 
         /* list all DC values before OUs */
@@ -12755,4 +13361,5 @@
                         XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
                     #endif
+                        WOLFSSL_MSG("Not enough space left for DC value");
                         return BUFFER_E;
                     }
@@ -12803,7 +13410,82 @@
 }
 
+/* Set Date validity from now until now + daysValid
+ * return size in bytes written to output, 0 on error */
+static int SetValidity(byte* output, int daysValid)
+{
+    byte before[MAX_DATE_SIZE];
+    byte  after[MAX_DATE_SIZE];
+
+    int beforeSz;
+    int afterSz;
+    int seqSz;
+
+    time_t now;
+    time_t then;
+    struct tm* tmpTime;
+    struct tm* expandedTime;
+    struct tm localTime;
+
+#if defined(NEED_TMP_TIME)
+    /* for use with gmtime_r */
+    struct tm tmpTimeStorage;
+    tmpTime = &tmpTimeStorage;
+#else
+    tmpTime = NULL;
+#endif
+    (void)tmpTime;
+
+    now = XTIME(0);
+
+    /* before now */
+    before[0] = ASN_GENERALIZED_TIME;
+    beforeSz = SetLength(ASN_GEN_TIME_SZ, before + 1) + 1;  /* gen tag */
+
+    /* subtract 1 day of seconds for more compliance */
+    then = now - 86400;
+    expandedTime = XGMTIME(&then, tmpTime);
+    if (expandedTime == NULL) {
+        WOLFSSL_MSG("XGMTIME failed");
+        return 0;   /* error */
+    }
+    localTime = *expandedTime;
+
+    /* adjust */
+    localTime.tm_year += 1900;
+    localTime.tm_mon +=    1;
+
+    SetTime(&localTime, before + beforeSz);
+    beforeSz += ASN_GEN_TIME_SZ;
+
+    after[0] = ASN_GENERALIZED_TIME;
+    afterSz  = SetLength(ASN_GEN_TIME_SZ, after + 1) + 1;  /* gen tag */
+
+    /* add daysValid of seconds */
+    then = now + (daysValid * (time_t)86400);
+    expandedTime = XGMTIME(&then, tmpTime);
+    if (expandedTime == NULL) {
+        WOLFSSL_MSG("XGMTIME failed");
+        return 0;   /* error */
+    }
+    localTime = *expandedTime;
+
+    /* adjust */
+    localTime.tm_year += 1900;
+    localTime.tm_mon  +=    1;
+
+    SetTime(&localTime, after + afterSz);
+    afterSz += ASN_GEN_TIME_SZ;
+
+    /* headers and output */
+    seqSz = SetSequence(beforeSz + afterSz, output);
+    XMEMCPY(output + seqSz, before, beforeSz);
+    XMEMCPY(output + seqSz + beforeSz, after, afterSz);
+
+    return seqSz + beforeSz + afterSz;
+}
+
 /* encode info from cert into DER encoded format */
 static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey,
-                      WC_RNG* rng, const byte* ntruKey, word16 ntruSz,
+                      WC_RNG* rng, const byte* ntruKey, word16 ntruSz, DsaKey* dsaKey,
                       ed25519_key* ed25519Key, ed448_key* ed448Key)
 {
@@ -12815,5 +13497,5 @@
     /* make sure at least one key type is provided */
     if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL &&
-                                          ed448Key == NULL && ntruKey == NULL) {
+            dsaKey == NULL && ed448Key == NULL && ntruKey == NULL) {
         return PUBLIC_KEY_E;
     }
@@ -12863,4 +13545,13 @@
 #endif
 
+#if !defined(NO_DSA) && !defined(HAVE_SELFTEST)
+    if (cert->keyType == DSA_KEY) {
+        if (dsaKey == NULL)
+            return PUBLIC_KEY_E;
+        der->publicKeySz = wc_SetDsaPublicKey(der->publicKey, dsaKey,
+                                           sizeof(der->publicKey), 1);
+    }
+#endif
+
 #ifdef HAVE_ED25519
     if (cert->keyType == ED25519_KEY) {
@@ -12926,5 +13617,5 @@
 
     /* subject name */
-#ifdef WOLFSSL_CERT_EXT
+#if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA)
     if (XSTRLEN((const char*)cert->sbjRaw) > 0) {
         /* Use the raw subject */
@@ -12954,5 +13645,5 @@
 
     /* issuer name */
-#ifdef WOLFSSL_CERT_EXT
+#if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA)
     if (XSTRLEN((const char*)cert->issRaw) > 0) {
         /* Use the raw issuer */
@@ -12961,4 +13652,5 @@
         der->issuerSz = min(sizeof(der->issuer),
                 (word32)XSTRLEN((const char*)cert->issRaw));
+
         /* header */
         idx = SetSequence(der->issuerSz, der->issuer);
@@ -13337,5 +14029,5 @@
 /* add signature to end of buffer, size of buffer assumed checked, return
    new length */
-static int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz,
+int AddSignature(byte* buf, int bodySz, const byte* sig, int sigSz,
                         int sigAlgoType)
 {
@@ -13366,5 +14058,5 @@
 static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz,
                        RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng,
-                       const byte* ntruKey, word16 ntruSz,
+                       DsaKey* dsaKey, const byte* ntruKey, word16 ntruSz,
                        ed25519_key* ed25519Key, ed448_key* ed448Key)
 {
@@ -13376,10 +14068,21 @@
 #endif
 
-    if (derBuffer == NULL) {
+    if (derBuffer == NULL)
         return BAD_FUNC_ARG;
-    }
-
-    cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY :
-            (ed25519Key ? ED25519_KEY : (ed448Key ? ED448_KEY : NTRU_KEY)));
+
+    if (eccKey)
+        cert->keyType = ECC_KEY;
+    else if (rsaKey)
+        cert->keyType = RSA_KEY;
+    else if (dsaKey)
+        cert->keyType = DSA_KEY;
+    else if (ed25519Key)
+        cert->keyType = ED25519_KEY;
+    else if (ed448Key)
+        cert->keyType = ED448_KEY;
+    else if (ntruKey)
+        cert->keyType = NTRU_KEY;
+    else
+        return BAD_FUNC_ARG;
 
 #ifdef WOLFSSL_SMALL_STACK
@@ -13389,5 +14092,5 @@
 #endif
 
-    ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz,
+    ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz, dsaKey,
                      ed25519Key, ed448Key);
     if (ret == 0) {
@@ -13411,4 +14114,5 @@
 {
     RsaKey*      rsaKey = NULL;
+    DsaKey*      dsaKey = NULL;
     ecc_key*     eccKey = NULL;
     ed25519_key* ed25519Key = NULL;
@@ -13417,4 +14121,6 @@
     if (keyType == RSA_TYPE)
         rsaKey = (RsaKey*)key;
+    else if (keyType == DSA_TYPE)
+        dsaKey = (DsaKey*)key;
     else if (keyType == ECC_TYPE)
         eccKey = (ecc_key*)key;
@@ -13424,6 +14130,6 @@
         ed448Key = (ed448_key*)key;
 
-    return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0,
-                       ed25519Key, ed448Key);
+    return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, dsaKey,
+                       NULL, 0, ed25519Key, ed448Key);
 }
 /* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */
@@ -13431,5 +14137,5 @@
              ecc_key* eccKey, WC_RNG* rng)
 {
-    return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0,
+    return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, NULL, 0,
                        NULL, NULL);
 }
@@ -13441,5 +14147,6 @@
                   const byte* ntruKey, word16 keySz, WC_RNG* rng)
 {
-    return MakeAnyCert(cert, derBuffer, derSz, NULL, NULL, rng, ntruKey, keySz, NULL);
+    return MakeAnyCert(cert, derBuffer, derSz, NULL, NULL, rng, NULL,
+            ntruKey, keySz, NULL, NULL);
 }
 
@@ -13452,7 +14159,4 @@
                         int extSz)
 {
-    const byte cpOid[] =
-        { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
-                         0x09, 0x07 };
     const byte erOid[] =
         { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
@@ -13474,5 +14178,5 @@
     byte erSet[MAX_SET_SZ];
 
-    output[0] = 0xa0;
+    output[0] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED;
     sz++;
 
@@ -13485,6 +14189,9 @@
         }
         cpSetSz = SetSet(cpStrSz + pwSz, cpSet);
-        cpSeqSz = SetSequence(sizeof(cpOid) + cpSetSz + cpStrSz + pwSz, cpSeq);
-        cpSz = cpSeqSz + sizeof(cpOid) + cpSetSz + cpStrSz + pwSz;
+        /* +2 for tag and length parts of the TLV triplet */
+        cpSeqSz = SetSequence(2 + sizeof(attrChallengePasswordOid) + cpSetSz +
+                cpStrSz + pwSz, cpSeq);
+        cpSz = cpSeqSz + 2 + sizeof(attrChallengePasswordOid) + cpSetSz +
+                cpStrSz + pwSz;
     }
 
@@ -13501,6 +14208,8 @@
         XMEMCPY(&output[sz], cpSeq, cpSeqSz);
         sz += cpSeqSz;
-        XMEMCPY(&output[sz], cpOid, sizeof(cpOid));
-        sz += sizeof(cpOid);
+        sz += SetObjectId(sizeof(attrChallengePasswordOid), output + sz);
+        XMEMCPY(&output[sz], attrChallengePasswordOid,
+                sizeof(attrChallengePasswordOid));
+        sz += sizeof(attrChallengePasswordOid);
         XMEMCPY(&output[sz], cpSet, cpSetSz);
         sz += cpSetSz;
@@ -13527,6 +14236,6 @@
 /* encode info from cert into DER encoded format */
 static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey,
-                         ecc_key* eccKey, ed25519_key* ed25519Key,
-                         ed448_key* ed448Key)
+                         DsaKey* dsaKey, ecc_key* eccKey,
+                         ed25519_key* ed25519Key, ed448_key* ed448Key)
 {
     (void)eccKey;
@@ -13538,5 +14247,5 @@
 
     if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL &&
-                                                             ed448Key == NULL) {
+            dsaKey == NULL && ed448Key == NULL) {
             return PUBLIC_KEY_E;
     }
@@ -13549,5 +14258,27 @@
 
     /* subject name */
-    der->subjectSz = SetName(der->subject, sizeof(der->subject), &cert->subject);
+#if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA)
+    if (XSTRLEN((const char*)cert->sbjRaw) > 0) {
+        /* Use the raw subject */
+        int idx;
+
+        der->subjectSz = min(sizeof(der->subject),
+                (word32)XSTRLEN((const char*)cert->sbjRaw));
+        /* header */
+        idx = SetSequence(der->subjectSz, der->subject);
+        if (der->subjectSz + idx > (int)sizeof(der->subject)) {
+            return SUBJECT_E;
+        }
+
+        XMEMCPY((char*)der->subject + idx, (const char*)cert->sbjRaw,
+                der->subjectSz);
+        der->subjectSz += idx;
+    }
+    else
+#endif
+    {
+        der->subjectSz = SetName(der->subject, sizeof(der->subject),
+                &cert->subject);
+    }
     if (der->subjectSz <= 0)
         return SUBJECT_E;
@@ -13563,6 +14294,17 @@
 #endif
 
+#if !defined(NO_DSA) && !defined(HAVE_SELFTEST)
+    if (cert->keyType == DSA_KEY) {
+        if (dsaKey == NULL)
+            return PUBLIC_KEY_E;
+        der->publicKeySz = wc_SetDsaPublicKey(der->publicKey, dsaKey,
+                                           sizeof(der->publicKey), 1);
+    }
+#endif
+
 #ifdef HAVE_ECC
     if (cert->keyType == ECC_KEY) {
+        if (eccKey == NULL)
+            return PUBLIC_KEY_E;
         der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1);
     }
@@ -13600,4 +14342,18 @@
     else
         der->caSz = 0;
+
+#ifdef WOLFSSL_ALT_NAMES
+    /* Alternative Name */
+    if (cert->altNamesSz) {
+        der->altNamesSz = SetAltNames(der->altNames, sizeof(der->altNames),
+                                      cert->altNames, cert->altNamesSz);
+        if (der->altNamesSz <= 0)
+            return ALT_NAME_E;
+
+        der->extensionsSz += der->altNamesSz;
+    }
+    else
+        der->altNamesSz = 0;
+#endif
 
 #ifdef WOLFSSL_CERT_EXT
@@ -13661,4 +14417,15 @@
                 return EXTENSIONS_E;
         }
+
+#ifdef WOLFSSL_ALT_NAMES
+        /* put Alternative Names */
+        if (der->altNamesSz) {
+            ret = SetExtensions(der->extensions, sizeof(der->extensions),
+                                &der->extensionsSz,
+                                der->altNames, der->altNamesSz);
+            if (ret <= 0)
+                return EXTENSIONS_E;
+        }
+#endif
 
 #ifdef WOLFSSL_CERT_EXT
@@ -13751,6 +14518,6 @@
 
 static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz,
-                   RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key,
-                   ed448_key* ed448Key)
+                   RsaKey* rsaKey, DsaKey* dsaKey, ecc_key* eccKey,
+                   ed25519_key* ed25519Key, ed448_key* ed448Key)
 {
     int ret;
@@ -13761,6 +14528,16 @@
 #endif
 
-    cert->keyType = eccKey ? ECC_KEY : (ed25519Key ? ED25519_KEY :
-                                       (ed448Key ? ED448_KEY: RSA_KEY));
+    if (eccKey)
+        cert->keyType = ECC_KEY;
+    else if (rsaKey)
+        cert->keyType = RSA_KEY;
+    else if (dsaKey)
+        cert->keyType = DSA_KEY;
+    else if (ed25519Key)
+        cert->keyType = ED25519_KEY;
+    else if (ed448Key)
+        cert->keyType = ED448_KEY;
+    else
+        return BAD_FUNC_ARG;
 
 #ifdef WOLFSSL_SMALL_STACK
@@ -13771,5 +14548,5 @@
 #endif
 
-    ret = EncodeCertReq(cert, der, rsaKey, eccKey, ed25519Key, ed448Key);
+    ret = EncodeCertReq(cert, der, rsaKey, dsaKey, eccKey, ed25519Key, ed448Key);
 
     if (ret == 0) {
@@ -13791,4 +14568,5 @@
 {
     RsaKey*      rsaKey = NULL;
+    DsaKey*      dsaKey = NULL;
     ecc_key*     eccKey = NULL;
     ed25519_key* ed25519Key = NULL;
@@ -13797,4 +14575,6 @@
     if (keyType == RSA_TYPE)
         rsaKey = (RsaKey*)key;
+    else if (keyType == DSA_TYPE)
+        dsaKey = (DsaKey*)key;
     else if (keyType == ECC_TYPE)
         eccKey = (ecc_key*)key;
@@ -13804,5 +14584,5 @@
         ed448Key = (ed448_key*)key;
 
-    return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, ed25519Key,
+    return MakeCertReq(cert, derBuffer, derSz, rsaKey, dsaKey, eccKey, ed25519Key,
                        ed448Key);
 }
@@ -13811,5 +14591,5 @@
                    RsaKey* rsaKey, ecc_key* eccKey)
 {
-    return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, NULL, NULL);
+    return MakeCertReq(cert, derBuffer, derSz, rsaKey, NULL, eccKey, NULL, NULL);
 }
 #endif /* WOLFSSL_CERT_REQ */
@@ -14003,5 +14783,5 @@
     /* ED448 public key */
     if (ed448Key != NULL)
-        bufferSz = SetEd448PublicKey(buffer, ed448Key, 0);
+        bufferSz = SetEd448PublicKey(buf, ed448Key, 0);
 #endif
 
@@ -14431,65 +15211,12 @@
 {
     int ret = 0;
-    byte tag;
-
-    if (decoded->extensions) {
-        int    length;
-        word32 maxExtensionsIdx;
-
-        decoded->srcIdx = decoded->extensionsIdx;
-        if (GetASNTag(decoded->source, &decoded->srcIdx, &tag, decoded->maxIdx)
-                != 0) {
-            return ASN_PARSE_E;
-        }
-
-        if (tag != ASN_EXTENSIONS) {
-            ret = ASN_PARSE_E;
-        }
-        else if (GetLength(decoded->source, &decoded->srcIdx, &length,
-                                                         decoded->maxIdx) < 0) {
-            ret = ASN_PARSE_E;
-        }
-        else if (GetSequence(decoded->source, &decoded->srcIdx, &length,
-                                                         decoded->maxIdx) < 0) {
-            ret = ASN_PARSE_E;
-        }
-        else {
-            maxExtensionsIdx = decoded->srcIdx + length;
-
-            while (decoded->srcIdx < maxExtensionsIdx) {
-                word32 oid;
-                word32 startIdx = decoded->srcIdx;
-                word32 tmpIdx;
-
-                if (GetSequence(decoded->source, &decoded->srcIdx, &length,
-                            decoded->maxIdx) < 0) {
-                    ret = ASN_PARSE_E;
-                    break;
-                }
-
-                tmpIdx = decoded->srcIdx;
-                decoded->srcIdx = startIdx;
-
-                if (GetAlgoId(decoded->source, &decoded->srcIdx, &oid,
-                              oidCertExtType, decoded->maxIdx) < 0) {
-                    ret = ASN_PARSE_E;
-                    break;
-                }
-
-                if (oid == ALT_NAMES_OID) {
-                    cert->altNamesSz = length + (tmpIdx - startIdx);
-
-                    if (cert->altNamesSz < (int)sizeof(cert->altNames))
-                        XMEMCPY(cert->altNames, &decoded->source[startIdx],
-                                cert->altNamesSz);
-                    else {
-                        cert->altNamesSz = 0;
-                        WOLFSSL_MSG("AltNames extensions too big");
-                        ret = ALT_NAME_E;
-                        break;
-                    }
-                }
-                decoded->srcIdx = tmpIdx + length;
-            }
+
+    cert->altNamesSz = 0;
+    if (decoded->altNames) {
+        ret = FlattenAltNames(cert->altNames,
+            sizeof(cert->altNames), decoded->altNames);
+        if (ret >= 0) {
+            cert->altNamesSz = ret;
+            ret = 0;
         }
     }
@@ -14878,10 +15605,11 @@
 
         if (ret >= 0) {
-            if ((((DecodedCert*)cert->decodedCert)->issuerRaw) &&
-                (((DecodedCert*)cert->decodedCert)->issuerRawLen <=
+            if ((((DecodedCert*)cert->decodedCert)->subjectRaw) &&
+                (((DecodedCert*)cert->decodedCert)->subjectRawLen <=
                         (int)sizeof(CertName))) {
+                /* Copy the subject to the issuer field */
                 XMEMCPY(cert->issRaw,
-                        ((DecodedCert*)cert->decodedCert)->issuerRaw,
-                        ((DecodedCert*)cert->decodedCert)->issuerRawLen);
+                        ((DecodedCert*)cert->decodedCert)->subjectRaw,
+                        ((DecodedCert*)cert->decodedCert)->subjectRawLen);
             }
 #ifndef WOLFSSL_CERT_GEN_CACHE
@@ -14902,5 +15630,5 @@
 
     if (cert == NULL) {
-     ret = BAD_FUNC_ARG;
+       ret = BAD_FUNC_ARG;
     }
     else {
@@ -15088,5 +15816,5 @@
     return 0;
 }
-#endif /* !NO_DH && WOLFSSL_QT || OPENSSL_ALL */
+#endif /* !NO_DH && (WOLFSSL_QT || OPENSSL_ALL) */
 
 #ifdef HAVE_ECC
@@ -15113,5 +15841,5 @@
 
     /* store r */
-    rSz = SetASNIntMP(r, -1, &out[idx]);
+    rSz = SetASNIntMP(r, *outLen - idx, &out[idx]);
     if (rSz < 0)
         return rSz;
@@ -15119,5 +15847,5 @@
 
     /* store s */
-    sSz = SetASNIntMP(s, -1, &out[idx]);
+    sSz = SetASNIntMP(s, *outLen - idx, &out[idx]);
     if (sSz < 0)
         return sSz;
@@ -15129,8 +15857,84 @@
 }
 
-
-/* Der Decode ECC-DSA Signature, r & s stored as big ints */
-int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s)
-{
+/* determine if leading bit is set */
+static int is_leading_bit_set(const byte* input, word32 sz)
+{
+    byte c = 0;
+    if (sz > 0)
+        c = input[0];
+    return (c & 0x80) != 0;
+}
+static int trim_leading_zeros(const byte** input, word32 sz)
+{
+    int i, leadingZeroCount = 0;
+    const byte* tmp = *input;
+    for (i=0; i<(int)sz; i++) {
+        if (tmp[i] != 0)
+            break;
+        leadingZeroCount++;
+    }
+    /* catch all zero case */
+    if (sz > 0 && leadingZeroCount == (int)sz) {
+        leadingZeroCount--;
+    }
+    *input += leadingZeroCount;
+    sz -= leadingZeroCount;
+    return sz;
+}
+
+/* Der Encode r & s ints into out, outLen is (in/out) size */
+/* All input/outputs are assumed to be big-endian */
+int StoreECC_DSA_Sig_Bin(byte* out, word32* outLen, const byte* r, word32 rLen, 
+    const byte* s, word32 sLen)
+{
+    int ret;
+    word32 idx;
+    word32 headerSz = 4;   /* 2*ASN_TAG + 2*LEN(ENUM) */
+    int rAddLeadZero, sAddLeadZero;
+
+    if ((out == NULL) || (outLen == NULL) || (r == NULL) || (s == NULL))
+        return BAD_FUNC_ARG;
+
+    /* Trim leading zeros */
+    rLen = trim_leading_zeros(&r, rLen);
+    sLen = trim_leading_zeros(&s, sLen);
+    /* If the leading bit on the INTEGER is a 1, add a leading zero */
+    /* Add leading zero if MSB is set */
+    rAddLeadZero = is_leading_bit_set(r, rLen);
+    sAddLeadZero = is_leading_bit_set(s, sLen);
+
+    if (*outLen < (rLen + rAddLeadZero + sLen + sAddLeadZero +
+                   headerSz + 2))  /* SEQ_TAG + LEN(ENUM) */
+        return BUFFER_E;
+
+    idx = SetSequence(rLen+rAddLeadZero + sLen+sAddLeadZero + headerSz, out);
+
+    /* store r */
+    ret = SetASNInt(rLen, rAddLeadZero ? 0x80 : 0x00, &out[idx]);
+    if (ret < 0)
+        return ret;
+    idx += ret;
+    XMEMCPY(&out[idx], r, rLen);
+    idx += rLen;
+
+    /* store s */
+    ret = SetASNInt(sLen, sAddLeadZero ? 0x80 : 0x00, &out[idx]);
+    if (ret < 0)
+        return ret;
+    idx += ret;
+    XMEMCPY(&out[idx], s, sLen);
+    idx += sLen;
+
+    *outLen = idx;
+
+    return 0;
+}
+
+/* Der Decode ECC-DSA Signature with R/S as unsigned bin */
+/* All input/outputs are assumed to be big-endian */
+int DecodeECC_DSA_Sig_Bin(const byte* sig, word32 sigLen, byte* r, word32* rLen,
+    byte* s, word32* sLen)
+{
+    int    ret;
     word32 idx = 0;
     int    len = 0;
@@ -15152,4 +15956,47 @@
 #endif
 
+    ret = GetASNInt(sig, &idx, &len, sigLen);
+    if (ret != 0)
+        return ret;
+    if (rLen)
+        *rLen = len;
+    if (r)
+        XMEMCPY(r, (byte*)sig + idx, len);
+    idx += len;
+
+    ret = GetASNInt(sig, &idx, &len, sigLen);
+    if (ret != 0)
+        return ret;
+    if (sLen)
+        *sLen = len;
+    if (s)
+        XMEMCPY(s, (byte*)sig + idx, len);
+
+    return ret;
+}
+#endif
+
+#if defined(HAVE_ECC) || !defined(NO_DSA)
+int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s)
+{
+    word32 idx = 0;
+    int    len = 0;
+
+    if (GetSequence(sig, &idx, &len, sigLen) < 0) {
+        return ASN_ECC_KEY_E;
+    }
+
+#ifndef NO_STRICT_ECDSA_LEN
+    /* enable strict length checking for signature */
+    if (sigLen != idx + (word32)len) {
+        return ASN_ECC_KEY_E;
+    }
+#else
+    /* allow extra signature bytes at end */
+    if ((word32)len > (sigLen - idx)) {
+        return ASN_ECC_KEY_E;
+    }
+#endif
+
     if (GetInt(r, sig, &idx, sigLen) < 0) {
         return ASN_ECC_KEY_E;
@@ -15157,4 +16004,5 @@
 
     if (GetInt(s, sig, &idx, sigLen) < 0) {
+        mp_clear(r);
         return ASN_ECC_KEY_E;
     }
@@ -15162,6 +16010,7 @@
     return 0;
 }
-
-
+#endif
+
+#ifdef HAVE_ECC
 int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
                         word32 inSz)
@@ -15175,5 +16024,5 @@
 #ifdef WOLFSSL_SMALL_STACK
     byte* priv;
-    byte* pub;
+    byte* pub = NULL;
 #else
     byte priv[ECC_MAXSIZE+1];
@@ -15203,22 +16052,16 @@
     if (GetLength(input, inOutIdx, &length, inSz) < 0)
         return ASN_PARSE_E;
-
-    if (length > ECC_MAXSIZE)
+    privSz = length;
+
+    if (privSz > ECC_MAXSIZE)
         return BUFFER_E;
 
 #ifdef WOLFSSL_SMALL_STACK
-    priv = (byte*)XMALLOC(ECC_MAXSIZE+1, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    priv = (byte*)XMALLOC(privSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
     if (priv == NULL)
         return MEMORY_E;
-
-    pub = (byte*)XMALLOC(2*(ECC_MAXSIZE+1), key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-    if (pub == NULL) {
-        XFREE(priv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
-        return MEMORY_E;
-    }
 #endif
 
     /* priv key */
-    privSz = length;
     XMEMCPY(priv, &input[*inOutIdx], privSz);
     *inOutIdx += length;
@@ -15264,11 +16107,19 @@
                 /* pub key */
                 pubSz = length;
-                if (pubSz < 2*(ECC_MAXSIZE+1)) {
-                    XMEMCPY(pub, &input[*inOutIdx], pubSz);
-                    *inOutIdx += length;
-                    pubData = pub;
+                if (pubSz > 2*(ECC_MAXSIZE+1))
+                    ret = BUFFER_E;
+                else {
+            #ifdef WOLFSSL_SMALL_STACK
+                    pub = (byte*)XMALLOC(pubSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+                    if (pub == NULL)
+                        ret = MEMORY_E;
+                    else
+            #endif
+                    {
+                        XMEMCPY(pub, &input[*inOutIdx], pubSz);
+                        *inOutIdx += length;
+                        pubData = pub;
+                    }
                 }
-                else
-                    ret = BUFFER_E;
             }
         }
@@ -15370,9 +16221,9 @@
                           ecc_key* key, word32 inSz)
 {
-    int    length;
     int    ret;
+    int    version, length;
     int    curve_id = ECC_CURVE_DEF;
     word32 oidSum, localIdx;
-    byte   tag;
+    byte   tag, isPrivFormat = 0;
 
     if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
@@ -15382,10 +16233,42 @@
         return ASN_PARSE_E;
 
-    if (GetSequence(input, inOutIdx, &length, inSz) < 0)
-        return ASN_PARSE_E;
-
-    ret = SkipObjectId(input, inOutIdx, inSz);
-    if (ret != 0)
-        return ret;
+    /* Check if ECC private key is being used and skip private portion */
+    if (GetMyVersion(input, inOutIdx, &version, inSz) >= 0) {
+        isPrivFormat = 1;
+
+        /* Type private key */
+        if (*inOutIdx >= inSz)
+            return ASN_PARSE_E;
+        tag = input[*inOutIdx];
+        *inOutIdx += 1;
+        if (tag != 4 && tag != 6 && tag != 7)
+            return ASN_PARSE_E;
+
+        /* Skip Private Key */
+        if (GetLength(input, inOutIdx, &length, inSz) < 0)
+            return ASN_PARSE_E;
+        if (length > ECC_MAXSIZE)
+            return BUFFER_E;
+        *inOutIdx += length;
+
+        /* Private Curve Header */
+        if (*inOutIdx >= inSz)
+            return ASN_PARSE_E;
+        tag = input[*inOutIdx];
+        *inOutIdx += 1;
+        if (tag != ECC_PREFIX_0)
+            return ASN_ECC_KEY_E;
+        if (GetLength(input, inOutIdx, &length, inSz) <= 0)
+            return ASN_PARSE_E;
+    }
+    /* Standard ECC public key */
+    else {
+        if (GetSequence(input, inOutIdx, &length, inSz) < 0)
+            return ASN_PARSE_E;
+
+        ret = SkipObjectId(input, inOutIdx, inSz);
+        if (ret != 0)
+            return ret;
+    }
 
     if (*inOutIdx >= inSz) {
@@ -15542,7 +16425,21 @@
 
         /* get curve id */
-        curve_id = wc_ecc_get_oid(oidSum, NULL, 0);
-        if (curve_id < 0)
+        if ((ret = CheckCurve(oidSum)) < 0)
             return ECC_CURVE_OID_E;
+        else {
+            curve_id = ret;
+        }
+    }
+
+    if (isPrivFormat) {
+        /* Public Curve Header - skip */
+        if (*inOutIdx >= inSz)
+            return ASN_PARSE_E;
+        tag = input[*inOutIdx];
+        *inOutIdx += 1;
+        if (tag != ECC_PREFIX_1)
+            return ASN_ECC_KEY_E;
+        if (GetLength(input, inOutIdx, &length, inSz) <= 0)
+            return ASN_PARSE_E;
     }
 
@@ -15572,8 +16469,14 @@
     byte   ver[MAX_VERSION_SZ];
     byte   seq[MAX_SEQ_SZ];
-    byte   *prv = NULL, *pub = NULL;
     int    ret, totalSz, curveSz, verSz;
     int    privHdrSz  = ASN_ECC_HEADER_SZ;
     int    pubHdrSz   = ASN_ECC_CONTEXT_SZ + ASN_ECC_HEADER_SZ;
+#ifdef WOLFSSL_NO_MALLOC
+    byte   prv[MAX_ECC_BYTES + ASN_ECC_HEADER_SZ + MAX_SEQ_SZ];
+    byte   pub[(MAX_ECC_BYTES * 2) + 1 + ASN_ECC_CONTEXT_SZ + 
+                              ASN_ECC_HEADER_SZ + MAX_SEQ_SZ];
+#else
+    byte   *prv = NULL, *pub = NULL;
+#endif
 
     word32 idx = 0, prvidx = 0, pubidx = 0, curveidx = 0;
@@ -15595,4 +16498,5 @@
     /* private */
     privSz = key->dp->size;
+#ifndef WOLFSSL_NO_MALLOC
     prv = (byte*)XMALLOC(privSz + privHdrSz + MAX_SEQ_SZ,
                          key->heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -15600,8 +16504,15 @@
         return MEMORY_E;
     }
+#else
+    if (sizeof(prv) < privSz + privHdrSz + MAX_SEQ_SZ) {
+        return BUFFER_E;
+    }
+#endif
     prvidx += SetOctetString8Bit(key->dp->size, &prv[prvidx]);
     ret = wc_ecc_export_private_only(key, prv + prvidx, &privSz);
     if (ret < 0) {
+    #ifndef WOLFSSL_NO_MALLOC
         XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
         return ret;
     }
@@ -15612,8 +16523,11 @@
         ret = wc_ecc_export_x963(key, NULL, &pubSz);
         if (ret != LENGTH_ONLY_E) {
+        #ifndef WOLFSSL_NO_MALLOC
             XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        #endif
             return ret;
         }
 
+    #ifndef WOLFSSL_NO_MALLOC
         pub = (byte*)XMALLOC(pubSz + pubHdrSz + MAX_SEQ_SZ,
                              key->heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -15622,4 +16536,9 @@
             return MEMORY_E;
         }
+    #else
+        if (sizeof(pub) < pubSz + pubHdrSz + MAX_SEQ_SZ) {
+            return BUFFER_E;
+        }
+    #endif
 
         pub[pubidx++] = ECC_PREFIX_1;
@@ -15633,6 +16552,8 @@
         ret = wc_ecc_export_x963(key, pub + pubidx, &pubSz);
         if (ret != 0) {
+        #ifndef WOLFSSL_NO_MALLOC
             XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
             XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+        #endif
             return ret;
         }
@@ -15646,8 +16567,10 @@
     totalSz = prvidx + pubidx + curveidx + verSz + seqSz;
     if (totalSz > (int)inLen) {
+        #ifndef WOLFSSL_NO_MALLOC
         XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
         if (pubIn) {
             XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
         }
+        #endif
         return BAD_FUNC_ARG;
     }
@@ -15665,5 +16588,7 @@
     XMEMCPY(output + idx, prv, prvidx);
     idx += prvidx;
+#ifndef WOLFSSL_NO_MALLOC
     XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
 
     /* curve */
@@ -15675,5 +16600,7 @@
         XMEMCPY(output + idx, pub, pubidx);
         /* idx += pubidx;  not used after write, if more data remove comment */
+    #ifndef WOLFSSL_NO_MALLOC
         XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
     }
 
@@ -15697,5 +16624,6 @@
 
 #ifdef HAVE_PKCS8
-/* Write only private ecc key to unencrypted PKCS#8 format.
+/* Write only private ecc key or both private and public parts to unencrypted
+ * PKCS#8 format.
  *
  * If output is NULL, places required PKCS#8 buffer size in outLen and
@@ -15703,5 +16631,6 @@
  *
  * return length on success else < 0 */
-int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen)
+static int eccToPKCS8(ecc_key* key, byte* output, word32* outLen,
+        int includePublic)
 {
     int ret, tmpDerSz;
@@ -15710,7 +16639,11 @@
     word32 pkcs8Sz = 0;
     const byte* curveOID = NULL;
+#ifdef WOLFSSL_NO_MALLOC
+    byte  tmpDer[ECC_BUFSIZE];
+#else
     byte* tmpDer = NULL;
-
-    if (key == NULL || outLen == NULL)
+#endif
+
+    if (key == NULL || key->dp == NULL || outLen == NULL)
         return BAD_FUNC_ARG;
 
@@ -15721,14 +16654,17 @@
         return ret;
 
+#ifndef WOLFSSL_NO_MALLOC
     /* temp buffer for plain DER key */
     tmpDer = (byte*)XMALLOC(ECC_BUFSIZE, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
     if (tmpDer == NULL)
         return MEMORY_E;
-
+#endif
     XMEMSET(tmpDer, 0, ECC_BUFSIZE);
 
-    tmpDerSz = wc_BuildEccKeyDer(key, tmpDer, ECC_BUFSIZE, 0);
+    tmpDerSz = wc_BuildEccKeyDer(key, tmpDer, ECC_BUFSIZE, includePublic);
     if (tmpDerSz < 0) {
+    #ifndef WOLFSSL_NO_MALLOC
         XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
         return tmpDerSz;
     }
@@ -15738,15 +16674,22 @@
                             curveOID, oidSz);
     if (ret != LENGTH_ONLY_E) {
+    #ifndef WOLFSSL_NO_MALLOC
         XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
         return ret;
     }
 
     if (output == NULL) {
+    #ifndef WOLFSSL_NO_MALLOC
         XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
         *outLen = pkcs8Sz;
         return LENGTH_ONLY_E;
 
-    } else if (*outLen < pkcs8Sz) {
+    }
+    else if (*outLen < pkcs8Sz) {
+    #ifndef WOLFSSL_NO_MALLOC
         XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
         WOLFSSL_MSG("Input buffer too small for ECC PKCS#8 key");
         return BUFFER_E;
@@ -15756,12 +16699,33 @@
                             algoID, curveOID, oidSz);
     if (ret < 0) {
+    #ifndef WOLFSSL_NO_MALLOC
         XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+    #endif
         return ret;
     }
 
+#ifndef WOLFSSL_NO_MALLOC
     XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
+#endif
 
     *outLen = ret;
     return ret;
+}
+
+/* Write only private ecc key to unencrypted PKCS#8 format.
+ *
+ * return length on success else < 0 */
+int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen)
+{
+    return eccToPKCS8(key, output, outLen, 0);
+}
+
+/* Write both private and public ecc keys to unencrypted PKCS#8 format.
+ *
+ * return length on success else < 0 */
+int wc_EccKeyToPKCS8(ecc_key* key, byte* output,
+                     word32* outLen)
+{
+    return eccToPKCS8(key, output, outLen, 1);
 }
 #endif /* HAVE_PKCS8 */
@@ -16188,10 +17152,9 @@
 
 
-static int DecodeSingleResponse(byte* source,
-                            word32* ioIndex, OcspResponse* resp, word32 size)
-{
-    word32 idx = *ioIndex, prevIndex, oid, localIdx;
-    int length, wrapperSz;
-    CertStatus* cs = resp->status;
+static int DecodeSingleResponse(byte* source, word32* ioIndex, word32 size,
+                                int wrapperSz, OcspEntry* single)
+{
+    word32 idx = *ioIndex, prevIndex, oid, localIdx, certIdIdx;
+    int length;
     int ret;
     byte tag;
@@ -16199,12 +17162,5 @@
     WOLFSSL_ENTER("DecodeSingleResponse");
 
-    /* Outer wrapper of the SEQUENCE OF Single Responses. */
-    if (GetSequence(source, &idx, &wrapperSz, size) < 0)
-        return ASN_PARSE_E;
-
     prevIndex = idx;
-
-    /* When making a request, we only request one status on one certificate
-     * at a time. There should only be one SingleResponse */
 
     /* Wrapper around the Single Response */
@@ -16213,14 +17169,18 @@
 
     /* Wrapper around the CertID */
+    certIdIdx = idx;
     if (GetSequence(source, &idx, &length, size) < 0)
         return ASN_PARSE_E;
-    /* Skip the hash algorithm */
-    if (GetAlgoId(source, &idx, &oid, oidIgnoreType, size) < 0)
-        return ASN_PARSE_E;
+    single->rawCertId = source + certIdIdx;
+    /* Hash algorithm */
+    ret = GetAlgoId(source, &idx, &oid, oidIgnoreType, size);
+    if (ret < 0)
+        return ret;
+    single->hashAlgoOID = oid;
     /* Save reference to the hash of CN */
     ret = GetOctetString(source, &idx, &length, size);
     if (ret < 0)
         return ret;
-    resp->issuerHash = source + idx;
+    XMEMCPY(single->issuerHash, source + idx, length);
     idx += length;
     /* Save reference to the hash of the issuer public key */
@@ -16228,12 +17188,13 @@
     if (ret < 0)
         return ret;
-    resp->issuerKeyHash = source + idx;
+    XMEMCPY(single->issuerKeyHash, source + idx, length);
     idx += length;
 
     /* Get serial number */
-    if (GetSerialNumber(source, &idx, cs->serial, &cs->serialSz, size) < 0)
+    if (GetSerialNumber(source, &idx, single->status->serial, &single->status->serialSz, size) < 0)
         return ASN_PARSE_E;
-
-    if ( idx >= size )
+    single->rawCertIdSize = idx - certIdIdx;
+
+    if (idx >= size)
         return BUFFER_E;
 
@@ -16242,9 +17203,9 @@
     {
         case (ASN_CONTEXT_SPECIFIC | CERT_GOOD):
-            cs->status = CERT_GOOD;
+            single->status->status = CERT_GOOD;
             idx++;
             break;
         case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_REVOKED):
-            cs->status = CERT_REVOKED;
+            single->status->status = CERT_REVOKED;
             if (GetLength(source, &idx, &length, size) < 0)
                 return ASN_PARSE_E;
@@ -16252,5 +17213,5 @@
             break;
         case (ASN_CONTEXT_SPECIFIC | CERT_UNKNOWN):
-            cs->status = CERT_UNKNOWN;
+            single->status->status = CERT_UNKNOWN;
             idx++;
             break;
@@ -16260,21 +17221,21 @@
 
 #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-    cs->thisDateAsn = source + idx;
+    single->status->thisDateAsn = source + idx;
     localIdx = 0;
-    if (GetDateInfo(cs->thisDateAsn, &localIdx, NULL,
-                    (byte*)&cs->thisDateParsed.type,
-                    &cs->thisDateParsed.length, size) < 0)
+    if (GetDateInfo(single->status->thisDateAsn, &localIdx, NULL,
+                    (byte*)&single->status->thisDateParsed.type,
+                    &single->status->thisDateParsed.length, size) < 0)
         return ASN_PARSE_E;
-    XMEMCPY(cs->thisDateParsed.data,
-            cs->thisDateAsn + localIdx - cs->thisDateParsed.length,
-            cs->thisDateParsed.length);
-#endif
-    if (GetBasicDate(source, &idx, cs->thisDate,
-                                                &cs->thisDateFormat, size) < 0)
+    XMEMCPY(single->status->thisDateParsed.data,
+            single->status->thisDateAsn + localIdx - single->status->thisDateParsed.length,
+            single->status->thisDateParsed.length);
+#endif
+    if (GetBasicDate(source, &idx, single->status->thisDate,
+                                                &single->status->thisDateFormat, size) < 0)
         return ASN_PARSE_E;
 
 #ifndef NO_ASN_TIME
 #ifndef WOLFSSL_NO_OCSP_DATE_CHECK
-    if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE))
+    if (!XVALIDATE_DATE(single->status->thisDate, single->status->thisDateFormat, BEFORE))
         return ASN_BEFORE_DATE_E;
 #endif
@@ -16283,5 +17244,4 @@
     /* The following items are optional. Only check for them if there is more
      * unprocessed data in the singleResponse wrapper. */
-
     localIdx = idx;
     if (((int)(idx - prevIndex) < wrapperSz) &&
@@ -16293,21 +17253,21 @@
             return ASN_PARSE_E;
 #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
-        cs->nextDateAsn = source + idx;
+        single->status->nextDateAsn = source + idx;
         localIdx = 0;
-        if (GetDateInfo(cs->nextDateAsn, &localIdx, NULL,
-                        (byte*)&cs->nextDateParsed.type,
-                        &cs->nextDateParsed.length, size) < 0)
+        if (GetDateInfo(single->status->nextDateAsn, &localIdx, NULL,
+                        (byte*)&single->status->nextDateParsed.type,
+                        &single->status->nextDateParsed.length, size) < 0)
             return ASN_PARSE_E;
-        XMEMCPY(cs->nextDateParsed.data,
-                cs->nextDateAsn + localIdx - cs->nextDateParsed.length,
-                cs->nextDateParsed.length);
-#endif
-        if (GetBasicDate(source, &idx, cs->nextDate,
-                                                &cs->nextDateFormat, size) < 0)
+        XMEMCPY(single->status->nextDateParsed.data,
+                single->status->nextDateAsn + localIdx - single->status->nextDateParsed.length,
+                single->status->nextDateParsed.length);
+#endif
+        if (GetBasicDate(source, &idx, single->status->nextDate,
+                                                &single->status->nextDateFormat, size) < 0)
             return ASN_PARSE_E;
 
 #ifndef NO_ASN_TIME
 #ifndef WOLFSSL_NO_OCSP_DATE_CHECK
-        if (!XVALIDATE_DATE(cs->nextDate, cs->nextDateFormat, AFTER))
+        if (!XVALIDATE_DATE(single->status->nextDate, single->status->nextDateFormat, AFTER))
             return ASN_AFTER_DATE_E;
 #endif
@@ -16315,4 +17275,5 @@
     }
 
+    /* Skip the optional extensions in singleResponse. */
     localIdx = idx;
     if (((int)(idx - prevIndex) < wrapperSz) &&
@@ -16418,4 +17379,6 @@
     int ret;
     byte tag;
+    int wrapperSz;
+    OcspEntry* single;
 
     WOLFSSL_ENTER("DecodeResponseData");
@@ -16459,6 +17422,26 @@
         return ASN_PARSE_E;
 
-    if ((ret = DecodeSingleResponse(source, &idx, resp, size)) < 0)
-        return ret; /* ASN_PARSE_E, ASN_BEFORE_DATE_E, ASN_AFTER_DATE_E */
+    /* Outer wrapper of the SEQUENCE OF Single Responses. */
+    if (GetSequence(source, &idx, &wrapperSz, size) < 0)
+        return ASN_PARSE_E;
+
+    localIdx = idx;
+    single = resp->single;
+
+    while (idx - localIdx < (word32)wrapperSz) {
+        ret = DecodeSingleResponse(source, &idx, size, wrapperSz, single);
+        if (ret < 0)
+            return ret; /* ASN_PARSE_E, ASN_BEFORE_DATE_E, ASN_AFTER_DATE_E */
+        if (idx - localIdx < (word32)wrapperSz) {
+            single->next = (OcspEntry*)XMALLOC(sizeof(OcspEntry), resp->heap, 
+                DYNAMIC_TYPE_OCSP_ENTRY);
+            if (single->next == NULL) {
+                return MEMORY_E;
+            }
+            single = single->next;
+            XMEMSET(single, 0, sizeof(OcspEntry));
+            single->isDynamic = 1;
+        }
+    }
 
     /*
@@ -16570,5 +17553,5 @@
         if ((cert.extExtKeyUsage & EXTKEYUSE_OCSP_SIGN) == 0) {
             if (XMEMCMP(cert.subjectHash,
-                        resp->issuerHash, KEYID_SIZE) == 0) {
+                        resp->single->issuerHash, OCSP_DIGEST_SIZE) == 0) {
                 WOLFSSL_MSG("\tOCSP Response signed by issuer");
             }
@@ -16605,7 +17588,7 @@
 
         #ifndef NO_SKID
-            ca = GetCA(cm, resp->issuerKeyHash);
+            ca = GetCA(cm, resp->single->issuerKeyHash);
         #else
-            ca = GetCA(cm, resp->issuerHash);
+            ca = GetCA(cm, resp->single->issuerHash);
         #endif
 
@@ -16632,16 +17615,29 @@
 
 
-void InitOcspResponse(OcspResponse* resp, CertStatus* status,
-                                                    byte* source, word32 inSz)
+void InitOcspResponse(OcspResponse* resp, OcspEntry* single, CertStatus* status,
+                      byte* source, word32 inSz, void* heap)
 {
     WOLFSSL_ENTER("InitOcspResponse");
 
     XMEMSET(status, 0, sizeof(CertStatus));
+    XMEMSET(single,  0, sizeof(OcspEntry));
     XMEMSET(resp,   0, sizeof(OcspResponse));
 
+    single->status       = status;
     resp->responseStatus = -1;
-    resp->status         = status;
+    resp->single         = single;
     resp->source         = source;
     resp->maxIdx         = inSz;
+    resp->heap           = heap;
+}
+
+void FreeOcspResponse(OcspResponse* resp)
+{
+    OcspEntry *single, *next;
+    for (single = resp->single; single; single = next) {
+        next = single->next;
+        if (single->isDynamic)
+            XFREE(single, resp->heap, DYNAMIC_TYPE_OCSP_ENTRY);
+    }
 }
 
@@ -16917,16 +17913,14 @@
 int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
 {
-    int cmp;
+    int cmp = -1; /* default as not matching, cmp gets set on each check */
+    OcspEntry *single, *next, *prev = NULL, *top;
 
     WOLFSSL_ENTER("CompareOcspReqResp");
 
-    if (req == NULL)
-    {
+    if (req == NULL) {
         WOLFSSL_MSG("\tReq missing");
         return -1;
     }
-
-    if (resp == NULL)
-    {
+    if (resp == NULL || resp->single == NULL) {
         WOLFSSL_MSG("\tResp missing");
         return 1;
@@ -16935,5 +17929,5 @@
     /* Nonces are not critical. The responder may not necessarily add
      * the nonce to the response. */
-    if (req->nonceSz
+    if (req->nonceSz && resp->nonce != NULL
 #ifndef WOLFSSL_FORCE_OCSP_NONCE_CHECK
             && resp->nonceSz != 0
@@ -16941,6 +17935,5 @@
     ) {
         cmp = req->nonceSz - resp->nonceSz;
-        if (cmp != 0)
-        {
+        if (cmp != 0) {
             WOLFSSL_MSG("\tnonceSz mismatch");
             return cmp;
@@ -16948,6 +17941,5 @@
 
         cmp = XMEMCMP(req->nonce, resp->nonce, req->nonceSz);
-        if (cmp != 0)
-        {
+        if (cmp != 0) {
             WOLFSSL_MSG("\tnonce mismatch");
             return cmp;
@@ -16955,29 +17947,28 @@
     }
 
-    cmp = XMEMCMP(req->issuerHash, resp->issuerHash, KEYID_SIZE);
-    if (cmp != 0)
-    {
-        WOLFSSL_MSG("\tissuerHash mismatch");
-        return cmp;
-    }
-
-    cmp = XMEMCMP(req->issuerKeyHash, resp->issuerKeyHash, KEYID_SIZE);
-    if (cmp != 0)
-    {
-        WOLFSSL_MSG("\tissuerKeyHash mismatch");
-        return cmp;
-    }
-
-    cmp = req->serialSz - resp->status->serialSz;
-    if (cmp != 0)
-    {
-        WOLFSSL_MSG("\tserialSz mismatch");
-        return cmp;
-    }
-
-    cmp = XMEMCMP(req->serial, resp->status->serial, req->serialSz);
-    if (cmp != 0)
-    {
-        WOLFSSL_MSG("\tserial mismatch");
+    /* match based on found status and return */
+    for (single = resp->single; single; single = next) {
+        cmp = req->serialSz - single->status->serialSz;
+        if (cmp == 0) {
+            if ((XMEMCMP(req->serial, single->status->serial, req->serialSz) == 0)
+             && (XMEMCMP(req->issuerHash, single->issuerHash, OCSP_DIGEST_SIZE) == 0)
+             && (XMEMCMP(req->issuerKeyHash, single->issuerKeyHash, OCSP_DIGEST_SIZE) == 0)) {
+                /* match found */
+                if (resp->single != single && prev) {
+                    /* move to top of list */
+                    top = resp->single;
+                    resp->single = single;
+                    prev->next = single->next;
+                    single->next = top;
+                }
+                break;
+            }
+        }
+        next = single->next;
+        prev = single;
+    }
+
+    if (cmp != 0) {
+        WOLFSSL_MSG("\trequest and response mismatch");
         return cmp;
     }
@@ -17352,5 +18343,5 @@
 
 
-/* prase crl buffer into decoded state, 0 on success */
+/* parse crl buffer into decoded state, 0 on success */
 int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm)
 {
@@ -17380,8 +18371,8 @@
     dcrl->sigIndex = len + idx;
 
-    if (ParseCRL_CertList(dcrl, buff, &idx, idx + len) < 0)
+    if (ParseCRL_CertList(dcrl, buff, &idx, dcrl->sigIndex) < 0)
         return ASN_PARSE_E;
 
-    if (ParseCRL_Extensions(dcrl, buff, &idx, idx + len) < 0)
+    if (ParseCRL_Extensions(dcrl, buff, &idx, dcrl->sigIndex) < 0)
         return ASN_PARSE_E;
 
@@ -17516,4 +18507,289 @@
 
 
+
+#ifdef HAVE_SMIME
+
+/*****************************************************************************
+* wc_MIME_parse_headers - Reads the char array in and parses out MIME headers
+* and parameters into headers.  Will continue until in has no more content.
+*
+* RETURNS:
+* returns zero on success, non-zero on error.
+*/
+int wc_MIME_parse_headers(char* in, int inLen, MimeHdr** headers)
+{
+    MimeHdr* nextHdr = NULL;
+    MimeHdr* curHdr = NULL;
+    MimeParam* nextParam = NULL;
+    size_t start = 0;
+    size_t end = 0;
+    char* nameAttr = NULL;
+    char* bodyVal = NULL;
+    MimeTypes mimeType = MIME_HDR;
+    MimeStatus mimeStatus = MIME_NAMEATTR;
+    int ret = -1;
+    size_t pos = 0;
+    size_t lineLen = 0;
+    char* curLine = NULL;
+    char* ptr = NULL;
+
+    if (in == NULL || inLen <= 0 || in[inLen] != '\0' || headers == NULL) {
+        ret = BAD_FUNC_ARG;
+        goto error;
+    }
+    nextHdr = (MimeHdr*)XMALLOC(sizeof(MimeHdr), NULL, DYNAMIC_TYPE_PKCS7);
+    nextParam = (MimeParam*)XMALLOC(sizeof(MimeParam), NULL,
+                                    DYNAMIC_TYPE_PKCS7);
+    if (nextHdr == NULL || nextParam == NULL) {
+        ret = MEMORY_E;
+        goto error;
+    }
+    XMEMSET(nextHdr, 0, (word32)sizeof(MimeHdr));
+    XMEMSET(nextParam, 0, (word32)sizeof(MimeParam));
+
+    curLine = XSTRTOK(in, "\r\n", &ptr);
+    if (curLine == NULL) {
+        ret = ASN_PARSE_E;
+        goto error;
+    }
+
+    while (curLine != NULL) {
+        /* Leftover from previous line, add params to previous header. */
+        if (curLine[0] == ' ' && curHdr) {
+            mimeType = MIME_PARAM;
+        }
+        else {
+            mimeType = MIME_HDR;
+        }
+        start = end = 0;
+        lineLen = XSTRLEN(curLine);
+
+        for (pos = 0; pos < lineLen; pos++) {
+            char cur = curLine[pos];
+
+            if (mimeStatus == MIME_NAMEATTR && ((cur == ':' &&
+                mimeType == MIME_HDR) || (cur == '=' &&
+                mimeType == MIME_PARAM))) {
+                mimeStatus = MIME_BODYVAL;
+                end = pos-1;
+                ret = wc_MIME_header_strip(curLine, &nameAttr, start, end);
+                if (ret) {
+                    goto error;
+                }
+                start = pos+1;
+            }
+            else if (mimeStatus == MIME_BODYVAL && cur == ';') {
+                end = pos-1;
+                ret = wc_MIME_header_strip(curLine, &bodyVal, start, end);
+                if (ret) {
+                    goto error;
+                }
+                if (mimeType == MIME_HDR) {
+                    nextHdr->name = nameAttr;
+                    nextHdr->body = bodyVal;
+                    nextHdr->next = curHdr;
+                    curHdr = nextHdr;
+                    nextHdr = (MimeHdr*)XMALLOC(sizeof(MimeHdr), NULL,
+                                                DYNAMIC_TYPE_PKCS7);
+                    if (nextHdr == NULL) {
+                        ret = MEMORY_E;
+                        goto error;
+                    }
+                    XMEMSET(nextHdr, 0, (word32)sizeof(MimeHdr));
+                }
+                else {
+                    nextParam->attribute = nameAttr;
+                    nextParam->value = bodyVal;
+                    nextParam->next = curHdr->params;
+                    curHdr->params = nextParam;
+                    nextParam = (MimeParam*)XMALLOC(sizeof(MimeParam), NULL,
+                                                    DYNAMIC_TYPE_PKCS7);
+                    if (nextParam == NULL) {
+                        ret = MEMORY_E;
+                        goto error;
+                    }
+                    XMEMSET(nextParam, 0, (word32)sizeof(MimeParam));
+                }
+                mimeType = MIME_PARAM;
+                mimeStatus = MIME_NAMEATTR;
+                start = pos+1;
+            }
+        }
+
+        end = lineLen-1;
+        /* Omit newline characters. */
+        while ((curLine[end] == '\r' || curLine[end] == '\n') && end > 0) {
+            end--;
+        }
+        if (end >= start && mimeStatus == MIME_BODYVAL) {
+            ret = wc_MIME_header_strip(curLine, &bodyVal, start, end);
+            if (ret) {
+                goto error;
+            }
+            if (mimeType == MIME_HDR) {
+                nextHdr->name = nameAttr;
+                nextHdr->body = bodyVal;
+                nextHdr->next = curHdr;
+                curHdr = nextHdr;
+                nextHdr = (MimeHdr*)XMALLOC(sizeof(MimeHdr), NULL,
+                                            DYNAMIC_TYPE_PKCS7);
+                if (nextHdr == NULL) {
+                    ret = MEMORY_E;
+                    goto error;
+                }
+                XMEMSET(nextHdr, 0, (word32)sizeof(MimeHdr));
+            } else {
+                nextParam->attribute = nameAttr;
+                nextParam->value = bodyVal;
+                nextParam->next = curHdr->params;
+                curHdr->params = nextParam;
+                nextParam = (MimeParam*)XMALLOC(sizeof(MimeParam), NULL,
+                                                DYNAMIC_TYPE_PKCS7);
+                if (nextParam == NULL) {
+                    ret = MEMORY_E;
+                    goto error;
+                }
+                XMEMSET(nextParam, 0, (word32)sizeof(MimeParam));
+            }
+        }
+
+        curLine = XSTRTOK(NULL, "\r\n", &ptr);
+        mimeStatus = MIME_NAMEATTR;
+    }
+
+    *headers = curHdr;
+    XFREE(nextHdr, NULL, DYNAMIC_TYPE_PKCS7);
+    XFREE(nextParam, NULL, DYNAMIC_TYPE_PKCS7);
+
+    return 0;
+
+error:
+    wc_MIME_free_hdrs(curHdr);
+    wc_MIME_free_hdrs(nextHdr);
+    XFREE(nameAttr, NULL, DYNAMIC_TYPE_PKCS7);
+    XFREE(bodyVal, NULL, DYNAMIC_TYPE_PKCS7);
+    XFREE(nextParam, NULL, DYNAMIC_TYPE_PKCS7);
+
+    return ret;
+}
+
+/*****************************************************************************
+* wc_MIME_header_strip - Reads the string in from indices start to end, strips
+* out disallowed/separator characters and places the rest into *out.
+*
+* RETURNS:
+* returns zero on success, non-zero on error.
+*/
+int wc_MIME_header_strip(char* in, char** out, size_t start, size_t end)
+{
+    size_t inPos = start;
+    size_t outPos = 0;
+    size_t inLen = 0;
+
+    if (end < start || in == NULL || out == NULL) {
+        return BAD_FUNC_ARG;
+    }
+
+    inLen = XSTRLEN(in);
+    if (start > inLen || end > inLen) {
+        return BAD_FUNC_ARG;
+    }
+
+    *out = (char*)XMALLOC(((end-start)+2)*sizeof(char), NULL,
+                          DYNAMIC_TYPE_PKCS7);
+    if (*out == NULL) {
+        return MEMORY_E;
+    }
+
+    while (inPos <= end) {
+        if (in[inPos] >= MIME_HEADER_ASCII_MIN && in[inPos] <=
+            MIME_HEADER_ASCII_MAX && in[inPos] != ';' && in[inPos] != '\"') {
+            (*out)[outPos] = in[inPos];
+            outPos++;
+        }
+        inPos++;
+    }
+    (*out)[outPos] = '\0';
+
+    return 0;
+}
+
+/*****************************************************************************
+* wc_MIME_find_header_name - Searches through all given headers until a header with
+* a name matching the provided name is found.
+*
+* RETURNS:
+* returns a pointer to the found header, if no match was found, returns NULL.
+*/
+MimeHdr* wc_MIME_find_header_name(const char* name, MimeHdr* header)
+{
+    size_t len = XSTRLEN(name);
+
+    while (header) {
+        if (!XSTRNCMP(name, header->name, len)) {
+            return header;
+        }
+        header = header->next;
+    }
+
+    return header;
+}
+
+/*****************************************************************************
+* wc_MIME_find_param_attr - Searches through all parameters until a parameter
+* with a attribute matching the provided attribute is found.
+*
+* RETURNS:
+* returns a pointer to the found parameter, if no match was found,
+* returns NULL.
+*/
+MimeParam* wc_MIME_find_param_attr(const char* attribute,
+                                    MimeParam* param)
+{
+    size_t len = XSTRLEN(attribute);
+
+    while (param) {
+        if (!XSTRNCMP(attribute, param->attribute, len)) {
+            return param;
+        }
+        param = param->next;
+    }
+
+    return param;
+}
+
+/*****************************************************************************
+* wc_MIME_free_hdrs - Frees all MIME headers, parameters and strings starting from
+* the provided header pointer.
+*
+* RETURNS:
+* returns zero on success, non-zero on error.
+*/
+int wc_MIME_free_hdrs(MimeHdr* head)
+{
+    MimeHdr* curHdr = NULL;
+    MimeParam* curParam = NULL;
+
+    while (head) {
+        while (head->params) {
+            curParam = head->params;
+            head->params = head->params->next;
+            XFREE(curParam->attribute, NULL, DYNAMIC_TYPE_PKCS7);
+            XFREE(curParam->value, NULL, DYNAMIC_TYPE_PKCS7);
+            XFREE(curParam, NULL, DYNAMIC_TYPE_PKCS7);
+        }
+        curHdr = head;
+        head = head->next;
+        XFREE(curHdr->name, NULL, DYNAMIC_TYPE_PKCS7);
+        XFREE(curHdr->body, NULL, DYNAMIC_TYPE_PKCS7);
+        XFREE(curHdr, NULL, DYNAMIC_TYPE_PKCS7);
+    }
+
+    return 0;
+}
+
+#endif /* HAVE_SMIME */
+
+
 #undef ERROR_OUT
 
