Browse Source

Tests starting to pass

Juliusz Sosinowicz 3 years ago
parent
commit
2689d499b9
14 changed files with 621 additions and 138 deletions
  1. BIN
      certs/csr.attr.der
  2. 0 0
      certs/csr.signed.der
  3. 5 0
      configure.ac
  4. 31 0
      src/internal.c
  5. 384 61
      src/ssl.c
  6. 42 16
      tests/api.c
  7. 97 12
      wolfcrypt/src/asn.c
  8. 26 46
      wolfcrypt/src/evp.c
  9. 1 2
      wolfcrypt/src/pkcs7.c
  10. 3 0
      wolfssl/internal.h
  11. 3 0
      wolfssl/openssl/pem.h
  12. 6 0
      wolfssl/openssl/ssl.h
  13. 6 1
      wolfssl/ssl.h
  14. 17 0
      wolfssl/wolfcrypt/asn.h

BIN
certs/csr.attr.der


+ 0 - 0
csr.signed.der → certs/csr.signed.der


+ 5 - 0
configure.ac

@@ -4316,6 +4316,11 @@ then
         ENABLED_SESSIONCERTS="yes"
         AM_CFLAGS="$AM_CFLAGS -DSESSION_CERTS"
     fi
+    
+    if test "x$ENABLED_DSA" = "xno"
+    then
+        AC_MSG_WARN([Enabling DSA with --enable-dsa is recommended for libest])
+    fi
 fi
 
 # MD4

+ 31 - 0
src/internal.c

@@ -9567,6 +9567,37 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert)
     else
         x509->subjectCN[0] = '\0';
 
+#ifdef WOLFSSL_CERT_REQ
+    /* CSR attributes */
+    if (dCert->cPwd) {
+        if (dCert->cPwdLen < CTC_NAME_SIZE) {
+            XMEMCPY(x509->challengePw, dCert->cPwd, dCert->cPwdLen);
+            x509->challengePw[dCert->cPwdLen] = '\0';
+            if (x509->challengePwAttr) {
+                wolfSSL_X509_ATTRIBUTE_free(x509->challengePwAttr);
+            }
+            x509->challengePwAttr = wolfSSL_X509_ATTRIBUTE_new();
+            if (x509->challengePwAttr) {
+                x509->challengePwAttr->value->value.asn1_string =
+                        wolfSSL_ASN1_STRING_new();
+                if (wolfSSL_ASN1_STRING_set(
+                        x509->challengePwAttr->value->value.asn1_string,
+                        dCert->cPwd, dCert->cPwdLen) != WOLFSSL_SUCCESS) {
+                    ret = MEMORY_E;
+                }
+                x509->challengePwAttr->value->type = V_ASN1_PRINTABLESTRING;
+            }
+            else {
+                ret = MEMORY_E;
+            }
+        }
+        else {
+            WOLFSSL_MSG("Challenge password too long");
+            ret = MEMORY_E;
+        }
+    }
+#endif
+
 #ifdef WOLFSSL_SEP
     {
         int minSz = min(dCert->deviceTypeSz, EXTERNAL_SERIAL_SIZE);

+ 384 - 61
src/ssl.c

@@ -442,7 +442,7 @@ WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method)
 int wolfSSL_CTX_up_ref(WOLFSSL_CTX* ctx)
 {
     int refCount = SSL_CTX_RefCount(ctx, 1);
-    return ((refCount > 1) ? 1 : 0);
+    return ((refCount > 1) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE);
 }
 #endif
 
@@ -3586,12 +3586,18 @@ WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap)
                                          DYNAMIC_TYPE_CERT_MANAGER);
     if (cm) {
         XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER));
+        cm->refCount = 1;
 
         if (wc_InitMutex(&cm->caLock) != 0) {
             WOLFSSL_MSG("Bad mutex init");
             wolfSSL_CertManagerFree(cm);
             return NULL;
         }
+        if (wc_InitMutex(&cm->refMutex) != 0) {
+            WOLFSSL_MSG("Bad mutex init");
+            wolfSSL_CertManagerFree(cm);
+            return NULL;
+        }
 
         #ifdef WOLFSSL_TRUST_PEER_CERT
         if (wc_InitMutex(&cm->tpLock) != 0) {
@@ -3623,37 +3629,62 @@ WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void)
 
 void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm)
 {
+    int doFree = 0;
     WOLFSSL_ENTER("wolfSSL_CertManagerFree");
 
     if (cm) {
-        #ifdef HAVE_CRL
-            if (cm->crl)
-                FreeCRL(cm->crl, 1);
-        #endif
-        #ifdef HAVE_OCSP
-            if (cm->ocsp)
-                FreeOCSP(cm->ocsp, 1);
-            XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
-        #if !defined(NO_WOLFSSL_SERVER) && \
-            (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
-             defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
-            if (cm->ocsp_stapling)
-                FreeOCSP(cm->ocsp_stapling, 1);
-        #endif
-        #endif
-        FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
-        wc_FreeMutex(&cm->caLock);
+        if (wc_LockMutex(&cm->refMutex) != 0) {
+            WOLFSSL_MSG("Couldn't lock cm mutex");
+        }
+        cm->refCount--;
+        if (cm->refCount == 0)
+            doFree = 1;
+        wc_UnLockMutex(&cm->refMutex);
+        if (doFree) {
+            #ifdef HAVE_CRL
+                if (cm->crl)
+                    FreeCRL(cm->crl, 1);
+            #endif
+            #ifdef HAVE_OCSP
+                if (cm->ocsp)
+                    FreeOCSP(cm->ocsp, 1);
+                XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL);
+            #if !defined(NO_WOLFSSL_SERVER) && \
+                (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \
+                 defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))
+                if (cm->ocsp_stapling)
+                    FreeOCSP(cm->ocsp_stapling, 1);
+            #endif
+            #endif
+            FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap);
+            wc_FreeMutex(&cm->caLock);
 
-        #ifdef WOLFSSL_TRUST_PEER_CERT
-        FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
-        wc_FreeMutex(&cm->tpLock);
-        #endif
+            #ifdef WOLFSSL_TRUST_PEER_CERT
+            FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
+            wc_FreeMutex(&cm->tpLock);
+            #endif
 
-        XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER);
+            XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER);
+        }
     }
 
 }
 
+int wolfSSL_CertManager_up_ref(WOLFSSL_CERT_MANAGER* cm)
+{
+    if (cm) {
+        if (wc_LockMutex(&cm->refMutex) != 0) {
+            WOLFSSL_MSG("Failed to lock cm mutex");
+        }
+        cm->refCount++;
+        wc_UnLockMutex(&cm->refMutex);
+
+        return WOLFSSL_SUCCESS;
+    }
+
+    return WOLFSSL_FAILURE;
+}
+
 #if defined(OPENSSL_EXTRA) && !defined(NO_FILESYSTEM)
 #if defined(WOLFSSL_SIGNER_DER_CERT)
 /******************************************************************************
@@ -15333,15 +15364,20 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
 
     void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str)
     {
-        if (ctx == NULL || str == NULL) {
+        if (ctx == NULL || str == NULL || ctx->cm == str->cm) {
             return;
         }
 
+        if (wolfSSL_CertManager_up_ref(str->cm) != WOLFSSL_SUCCESS) {
+            WOLFSSL_MSG("wolfSSL_CertManager_up_ref error");
+            return;
+        }
         /* free cert manager if have one */
         if (ctx->cm != NULL) {
             wolfSSL_CertManagerFree(ctx->cm);
         }
         ctx->cm               = str->cm;
+        ctx->x509_store.cm    = str->cm;
 
         /* free existing store if it exists */
         if (ctx->x509_store_pt != NULL) {
@@ -15888,6 +15924,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
             wc_RemoveErrorNode(0);
         }
         } while (ret >= 0);
+        wolfSSL_BIO_write(bio, "", 1);
     }
 #endif /* !NO_BIO */
 #endif /* OPENSSL_EXTRA || DEBUG_WOLFSSL_VERBOSE */
@@ -19534,6 +19571,98 @@ WOLFSSL_STACK *wolfSSL_NCONF_get_section(
         return NULL;
 }
 
+static char* expandValue(WOLFSSL_CONF *conf, const char* section,
+        char *str)
+{
+    int strLen = XSTRLEN(str);
+    char* ret = NULL;
+
+    /* Check to see if there is anything to expand */
+    if (XSTRNSTR(str, "$", strLen)) {
+        int idx = 0;
+        char* strIdx = str;
+        ret = (char*)XMALLOC(strLen + 1, NULL, DYNAMIC_TYPE_OPENSSL);
+        if (!ret) {
+            WOLFSSL_MSG("malloc error");
+            return str;
+        }
+
+        while (*strIdx) {
+            if (*strIdx == '$') {
+                /* Expand variable */
+                char* startIdx = ++strIdx;
+                char* endIdx;
+                const char* s = section;
+                const char* value;
+                char prevValue;
+
+                if (*startIdx == '{') {
+                    /* First read the section. Ex: ${ENV::COUNT} */
+                    s = ++startIdx;
+                    while (*strIdx && *strIdx != ':') strIdx++;
+                    if (!strIdx || s == strIdx || strIdx[1] != ':') {
+                        WOLFSSL_MSG("invalid section name in "
+                                    "variable expansion");
+                        goto expand_cleanup;
+                    }
+                    *strIdx = '\0';
+                    *strIdx += 2;
+                    startIdx = strIdx;
+                }
+                while (*strIdx && (XISALPHA(*strIdx) || *strIdx == '_'))
+                    strIdx++;
+                endIdx = strIdx;
+                if (startIdx == endIdx) {
+                    WOLFSSL_MSG("invalid variable name in config");
+                    goto expand_cleanup;
+                }
+                if (s != section) {
+                    /* We are expecting a trailing '}' */
+                    if (*strIdx != '}') {
+                        WOLFSSL_MSG("Missing '}' in variable");
+                        goto expand_cleanup;
+                    }
+                    strIdx++;
+                }
+                /* Save char value at the end of the name so that we can place
+                 * a null char there. */
+                prevValue = *endIdx;
+                *endIdx = '\0';
+                value = wolfSSL_NCONF_get_string(conf, s, startIdx);
+                *endIdx = prevValue;
+                /* Skip copy if no value or zero-length value */
+                if (value && *value) {
+                    int valueLen = XSTRLEN(value);
+                    char* newRet;
+                    /* This will allocate slightly more memory than necessary
+                     * but better be safe */
+                    strLen += valueLen;
+                    newRet = (char*)XREALLOC(ret, strLen + 1, NULL,
+                            DYNAMIC_TYPE_OPENSSL);
+                    if (!newRet) {
+                        WOLFSSL_MSG("realloc error");
+                        goto expand_cleanup;
+                    }
+                    ret = newRet;
+                    XMEMCPY(ret + idx, value, valueLen);
+                    idx += valueLen;
+                }
+            }
+            else {
+                ret[idx++] = *strIdx++;
+            }
+        }
+        ret[idx] = '\0';
+    }
+
+    return ret ? ret : str;
+
+expand_cleanup:
+    if (ret)
+        XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL);
+    return NULL;
+}
+
 #define SKIP_WHITESPACE(idx, max_idx) \
     while (idx < max_idx && (*idx == ' ' || *idx == '\t')) \
         {idx++;}
@@ -19632,6 +19761,7 @@ int wolfSSL_NCONF_load(WOLFSSL_CONF *conf, const char *file, long *eline)
             char* name;
             int   nameLen;
             char* value;
+            char* exValue; /* expanded value */
             int   valueLen;
             WOLFSSL_CONF_VALUE* newVal = NULL;
 
@@ -19663,12 +19793,22 @@ int wolfSSL_NCONF_load(WOLFSSL_CONF *conf, const char *file, long *eline)
             name[nameLen] = '\0';
             value[valueLen] = '\0';
 
+            if (!(exValue = expandValue(conf, section->section, value))) {
+                WOLFSSL_MSG("Variable expansion failed");
+                goto cleanup;
+            }
+
             if (!(newVal = wolfSSL_CONF_VALUE_new_values(section->section,
-                    name, value))) {
+                    name, exValue))) {
                 WOLFSSL_MSG("wolfSSL_CONF_VALUE_new_values error");
+                if (exValue != value)
+                    XFREE(exValue, NULL, DYNAMIC_TYPE_OPENSSL);
                 goto cleanup;
             }
 
+            if (exValue != value)
+                XFREE(exValue, NULL, DYNAMIC_TYPE_OPENSSL);
+
             if (wolfSSL_CONF_add_string(conf, section, newVal) !=
                     WOLFSSL_SUCCESS) {
                 WOLFSSL_MSG("wolfSSL_CONF_add_string error");
@@ -27089,6 +27229,13 @@ void wolfSSL_ASN1_TYPE_free(WOLFSSL_ASN1_TYPE* at)
             case V_ASN1_GENERALIZEDTIME:
                 wolfSSL_ASN1_TIME_free(at->value.generalizedtime);
                 break;
+            case V_ASN1_UTF8STRING:
+            case V_ASN1_PRINTABLESTRING:
+            case V_ASN1_T61STRING:
+            case V_ASN1_IA5STRING:
+            case V_ASN1_UNIVERSALSTRING:
+                wolfSSL_ASN1_STRING_free(at->value.asn1_string);
+                break;
             default:
                 WOLFSSL_MSG("Unknown or unsupported ASN1_TYPE");
                 break;
@@ -27190,10 +27337,14 @@ int wolfSSL_X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg,
 WOLFSSL_EVP_PKEY* wolfSSL_X509_PUBKEY_get(WOLFSSL_X509_PUBKEY* key)
 {
     WOLFSSL_ENTER("wolfSSL_X509_PUBKEY_get");
-    if(key == NULL || key->pkey == NULL){
+    if (key == NULL || key->pkey == NULL) {
         WOLFSSL_LEAVE("wolfSSL_X509_PUBKEY_get", BAD_FUNC_ARG);
         return NULL;
     }
+    if (wolfSSL_EVP_PKEY_up_ref(key->pkey) != WOLFSSL_SUCCESS) {
+        WOLFSSL_LEAVE("wolfSSL_X509_PUBKEY_get", BAD_MUTEX_E);
+        return NULL;
+    }
     WOLFSSL_LEAVE("wolfSSL_X509_PUBKEY_get", WOLFSSL_SUCCESS);
     return key->pkey;
 }
@@ -29775,6 +29926,10 @@ const WOLFSSL_ObjectInfo wolfssl_object_info[] = {
                                                             "jurisdictionCountryName"},
     { NID_jurisdictionStateOrProvinceName, NID_jurisdictionStateOrProvinceName,
             oidCertNameType, "jurisdictionST", "jurisdictionStateOrProvinceName"},
+#ifdef WOLFSSL_CERT_REQ
+    { NID_pkcs9_challengePassword, CHALLENGE_PASSWORD_OID,
+            oidCsrAttrType, "challengePassword", "challengePassword"},
+#endif
 #endif
 #ifdef OPENSSL_EXTRA /* OPENSSL_EXTRA_X509_SMALL only needs the above */
         /* oidHashType */
@@ -38425,10 +38580,10 @@ int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa)
         rsa->refCount++;
         wc_UnLockMutex(&rsa->refMutex);
 
-        return 1;
+        return WOLFSSL_SUCCESS;
     }
 
-    return 0;
+    return WOLFSSL_FAILURE;
 }
 
 /* increments ref count of WOLFSSL_X509. Return 1 on success, 0 on error */
@@ -38441,10 +38596,10 @@ int wolfSSL_X509_up_ref(WOLFSSL_X509* x509)
         x509->refCount++;
         wc_UnLockMutex(&x509->refMutex);
 
-        return 1;
+        return WOLFSSL_SUCCESS;
     }
 
-    return 0;
+    return WOLFSSL_FAILURE;
 }
 
 #endif /* OPENSSL_EXTRA || OPENSSL_ALL */
@@ -39182,6 +39337,12 @@ void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl)
             if (req->keyUsageSet)
                 cert->keyUsage = req->keyUsage;
             /* Extended Key Usage not supported. */
+    #endif
+    #ifdef WOLFSSL_CERT_REQ
+            if (XSTRLEN(cert->challengePw) > 0) {
+                XMEMCPY(cert->challengePw, req->challengePw, CTC_NAME_SIZE);
+                cert->challengePwPrintableString = 1;
+            }
     #endif
         }
 
@@ -41552,6 +41713,7 @@ err:
     {
         word32 oid = 0;
         word32 idx = 0;
+        int ret;
 
         WOLFSSL_ENTER("wolfSSL_OBJ_obj2nid");
 
@@ -41569,9 +41731,29 @@ err:
 
         if (o->nid > 0)
             return o->nid;
-        if (GetObjectId(o->obj, &idx, &oid, o->grp, o->objSz) < 0) {
-            WOLFSSL_MSG("Issue getting OID of object");
-            return -1;
+        if ((ret = GetObjectId(o->obj, &idx, &oid, o->grp, o->objSz)) < 0) {
+            if (ret == ASN_OBJECT_ID_E) {
+                /* Put ASN object tag in front and try again */
+                int len = SetObjectId(o->objSz, NULL) + o->objSz;
+                byte* buf = XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                if (!buf) {
+                    WOLFSSL_MSG("malloc error");
+                    return -1;
+                }
+                idx = SetObjectId(o->objSz, buf);
+                XMEMCPY(buf + idx, o->obj, o->objSz);
+                idx = 0;
+                ret = GetObjectId(buf, &idx, &oid, o->grp, len);
+                XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                if (ret < 0) {
+                    WOLFSSL_MSG("Issue getting OID of object");
+                    return -1;
+                }
+            }
+            else {
+                WOLFSSL_MSG("Issue getting OID of object");
+                return -1;
+            }
         }
 
         return oid2nid(oid, o->grp);
@@ -47149,6 +47331,7 @@ int wolfSSL_set_alpn_protos(WOLFSSL* ssl,
 
 int oid2nid(word32 oid, int grp)
 {
+    size_t i;
     /* get OID type */
     switch (grp) {
         /* oidHashType */
@@ -47470,9 +47653,23 @@ int oid2nid(word32 oid, int grp)
             }
             break;
 
+        case oidCsrAttrType:
+            switch (oid) {
+                case CHALLENGE_PASSWORD_OID:
+                    return NID_pkcs9_challengePassword;
+                case SERIAL_NUMBER_OID:
+                    return NID_serialNumber;
+            }
+            break;
+
         default:
             WOLFSSL_MSG("NID not in table");
-            return -1;
+    }
+    /* If not found in above switch then try the table */
+    for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++) {
+        if (wolfssl_object_info[i].id == (int)oid) {
+            return wolfssl_object_info[i].nid;
+        }
     }
 
     return -1;
@@ -50270,6 +50467,11 @@ int wolfSSL_PKCS7_encode_certs(PKCS7* pkcs7, WOLFSSL_STACK* certs,
         int hashOID = p7->hashOID;
         byte version = p7->version;
 
+        if (!certs->data.x509 || !certs->data.x509->derCert) {
+            WOLFSSL_MSG("Missing cert");
+            return WOLFSSL_FAILURE;
+        }
+
         if (wc_PKCS7_InitWithCert(p7, certs->data.x509->derCert->buffer,
                 certs->data.x509->derCert->length) != 0) {
             WOLFSSL_MSG("wc_PKCS7_InitWithCert error");
@@ -50283,6 +50485,10 @@ int wolfSSL_PKCS7_encode_certs(PKCS7* pkcs7, WOLFSSL_STACK* certs,
 
     /* Add the certs to the PKCS7 struct */
     while (certs) {
+        if (!certs->data.x509 || !certs->data.x509->derCert) {
+            WOLFSSL_MSG("Missing cert");
+            return WOLFSSL_FAILURE;
+        }
         if (wc_PKCS7_AddCertificate(p7, certs->data.x509->derCert->buffer,
                 certs->data.x509->derCert->length) != 0) {
             WOLFSSL_MSG("wc_PKCS7_AddCertificate error");
@@ -51165,7 +51371,11 @@ int wolfSSL_X509_REQ_sign(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey,
 int wolfSSL_X509_REQ_sign_ctx(WOLFSSL_X509 *req,
                               WOLFSSL_EVP_MD_CTX* md_ctx)
 {
-    return wolfSSL_X509_REQ_sign(req, md_ctx->pctx->pkey, wolfSSL_EVP_MD_CTX_md(md_ctx));
+    if (md_ctx && md_ctx->pctx)
+        return wolfSSL_X509_REQ_sign(req, md_ctx->pctx->pkey,
+                wolfSSL_EVP_MD_CTX_md(md_ctx));
+    else
+        return WOLFSSL_FAILURE;
 }
 
 #ifndef NO_WOLFSSL_STUB
@@ -51176,22 +51386,6 @@ int wolfSSL_X509_REQ_add_extensions(WOLFSSL_X509* req,
     (void)ext;
     return WOLFSSL_FAILURE;
 }
-
-int wolfSSL_X509_REQ_add1_attr_by_NID(WOLFSSL_X509 *req,
-                                      int nid, int type,
-                                      const unsigned char *bytes,
-                                      int len)
-{
-    WOLFSSL_ENTER("wolfSSL_X509_REQ_add1_attr_by_NID");
-    WOLFSSL_STUB("wolfSSL_X509_REQ_add1_attr_by_NID");
-    (void)req;
-    (void)nid;
-    (void)type;
-    (void)bytes;
-    (void)len;
-    return WOLFSSL_FAILURE;
-}
-
 int wolfSSL_X509_REQ_add1_attr_by_txt(WOLFSSL_X509 *req,
                               const char *attrname, int type,
                               const unsigned char *bytes, int len)
@@ -51205,28 +51399,157 @@ int wolfSSL_X509_REQ_add1_attr_by_txt(WOLFSSL_X509 *req,
     (void)len;
     return WOLFSSL_FAILURE;
 }
+#endif /* NO_WOLFSSL_STUB */
+
+int wolfSSL_X509_REQ_add1_attr_by_NID(WOLFSSL_X509 *req,
+                                      int nid, int type,
+                                      const unsigned char *bytes,
+                                      int len)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_REQ_add1_attr_by_NID");
+
+    if (!req || !bytes || type != MBSTRING_ASC) {
+        WOLFSSL_MSG("Bad parameter");
+        return WOLFSSL_FAILURE;
+    }
+
+    switch (nid) {
+    case NID_pkcs9_challengePassword:
+        if (len < 0)
+            len = XSTRLEN((char*)bytes);
+        if (len < CTC_NAME_SIZE) {
+            XMEMCPY(req->challengePw, bytes, len);
+            req->challengePw[len] = '\0';
+        }
+        else {
+            WOLFSSL_MSG("Challenge password too long");
+            return WOLFSSL_FAILURE;
+        }
+        if (req->challengePwAttr) {
+            wolfSSL_X509_ATTRIBUTE_free(req->challengePwAttr);
+        }
+        req->challengePwAttr = wolfSSL_X509_ATTRIBUTE_new();
+        if (req->challengePwAttr) {
+            req->challengePwAttr->value->value.asn1_string =
+                    wolfSSL_ASN1_STRING_new();
+            if (wolfSSL_ASN1_STRING_set(
+                    req->challengePwAttr->value->value.asn1_string,
+                    bytes, len) != WOLFSSL_SUCCESS) {
+                WOLFSSL_MSG("wolfSSL_ASN1_STRING_set error");
+                return WOLFSSL_FAILURE;
+            }
+            req->challengePwAttr->value->type = V_ASN1_PRINTABLESTRING;
+        }
+        else {
+            WOLFSSL_MSG("wolfSSL_X509_ATTRIBUTE_new error");
+            return WOLFSSL_FAILURE;
+        }
+        break;
+    default:
+        WOLFSSL_MSG("Unsupported attribute");
+        return WOLFSSL_FAILURE;
+    }
+    return WOLFSSL_SUCCESS;
+}
 
+
+/* Return NID as the attr index */
 int wolfSSL_X509_REQ_get_attr_by_NID(const WOLFSSL_X509 *req,
         int nid, int lastpos)
 {
     WOLFSSL_ENTER("wolfSSL_X509_REQ_get_attr_by_NID");
-    WOLFSSL_STUB("wolfSSL_X509_REQ_get_attr_by_NID");
-    (void)req;
-    (void)nid;
-    (void)lastpos;
-    return WOLFSSL_FATAL_ERROR;
+
+    /* Since we only support 1 attr per attr type then a lastpos of >= 0
+     * indicates that one was already returned */
+    if (!req || lastpos >= 0) {
+        WOLFSSL_MSG("Bad parameter");
+        return WOLFSSL_FATAL_ERROR;
+    }
+
+    switch (nid) {
+    case NID_pkcs9_challengePassword:
+        return req->challengePwAttr ? nid : WOLFSSL_FATAL_ERROR;
+    default:
+        WOLFSSL_MSG("Unsupported attribute");
+        return WOLFSSL_FATAL_ERROR;
+    }
 }
 
+/**
+ * @param req X509_REQ containing attribute
+ * @param loc NID of the attribute to return
+ */
 WOLFSSL_X509_ATTRIBUTE *wolfSSL_X509_REQ_get_attr(
         const WOLFSSL_X509 *req, int loc)
 {
     WOLFSSL_ENTER("wolfSSL_X509_REQ_get_attr");
-    WOLFSSL_STUB("wolfSSL_X509_REQ_get_attr");
-    (void)req;
-    (void)loc;
-    return NULL;
+
+    if (!req) {
+        WOLFSSL_MSG("Bad parameter");
+        return NULL;
+    }
+
+    switch (loc) {
+    case NID_pkcs9_challengePassword:
+        return req->challengePwAttr;
+    default:
+        WOLFSSL_MSG("Unsupported attribute");
+        return NULL;
+    }
+}
+
+WOLFSSL_X509_ATTRIBUTE* wolfSSL_X509_ATTRIBUTE_new(void)
+{
+    WOLFSSL_X509_ATTRIBUTE* ret;
+    WOLFSSL_ENTER("wolfSSL_X509_ATTRIBUTE_new");
+    ret = (WOLFSSL_X509_ATTRIBUTE*)XMALLOC(sizeof(WOLFSSL_X509_ATTRIBUTE),
+            NULL, DYNAMIC_TYPE_OPENSSL);
+    if (!ret) {
+        WOLFSSL_MSG("malloc error");
+        return NULL;
+    }
+    XMEMSET(ret, 0, sizeof(WOLFSSL_X509_ATTRIBUTE));
+    ret->object = wolfSSL_ASN1_OBJECT_new();
+    ret->value = wolfSSL_ASN1_TYPE_new();
+    /* Don't allocate ret->set since WOLFSSL_ASN1_TYPE
+     * is not supported as a stack type */
+    if (!ret->object || !ret->value) {
+        WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_new or wolfSSL_ASN1_TYPE_new error");
+        wolfSSL_X509_ATTRIBUTE_free(ret);
+        return NULL;
+    }
+    return ret;
+}
+
+void wolfSSL_X509_ATTRIBUTE_free(WOLFSSL_X509_ATTRIBUTE* attr)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_ATTRIBUTE_free");
+    if (attr) {
+        if (attr->object) {
+            wolfSSL_ASN1_OBJECT_free(attr->object);
+        }
+        if (attr->value) {
+            wolfSSL_ASN1_TYPE_free(attr->value);
+        }
+        if (attr->set) {
+            wolfSSL_sk_free(attr->set);
+        }
+        XFREE(attr, NULL, DYNAMIC_TYPE_OPENSSL);
+    }
+}
+
+WOLFSSL_ASN1_TYPE *wolfSSL_X509_ATTRIBUTE_get0_type(
+        WOLFSSL_X509_ATTRIBUTE *attr, int idx)
+{
+    WOLFSSL_ENTER("wolfSSL_X509_ATTRIBUTE_get0_type");
+
+    if (!attr || idx != 0) {
+        WOLFSSL_MSG("Bad parameter");
+        return NULL;
+    }
+
+    return attr->value;
 }
-#endif
 
 WOLFSSL_X509 *wolfSSL_X509_to_X509_REQ(WOLFSSL_X509 *x,
         WOLFSSL_EVP_PKEY *pkey, const WOLFSSL_EVP_MD *md)

+ 42 - 16
tests/api.c

@@ -30086,7 +30086,8 @@ static void test_wolfSSL_ERR_print_errors(void)
     AssertIntEQ(BIO_gets(bio, buf, sizeof(buf)), 57);
     AssertIntEQ(XSTRNCMP("error:295:wolfSSL library:unknown error number:asn.c:100",
                 buf, 56), 0);
-    AssertIntEQ(BIO_gets(bio, buf, sizeof(buf)), 0);
+    AssertIntEQ(BIO_gets(bio, buf, sizeof(buf)), 1);
+    AssertIntEQ(buf[0], '\0');
     AssertIntEQ(ERR_get_error_line(NULL, NULL), 0);
 
     BIO_free(bio);
@@ -33280,9 +33281,9 @@ static void test_wolfSSL_get_ciphers_compat(void)
 
 static void test_wolfSSL_X509_PUBKEY_get(void)
 {
-    WOLFSSL_X509_PUBKEY pubkey;
+    WOLFSSL_X509_PUBKEY pubkey = {0};
     WOLFSSL_X509_PUBKEY* key;
-    WOLFSSL_EVP_PKEY evpkey;
+    WOLFSSL_EVP_PKEY evpkey = {0};
     WOLFSSL_EVP_PKEY* evpPkey;
     WOLFSSL_EVP_PKEY* retEvpPkey;
 
@@ -37887,26 +37888,51 @@ static void test_wolfSSL_X509_CRL(void)
 
 static void test_wolfSSL_d2i_X509_REQ(void)
 {
-    const char* csrFile = "./csr.signed.der";
+    const char* csrFile = "./certs/csr.signed.der";
+    const char* csrPopFile = "./certs/csr.attr.der";
     BIO* bio = NULL;
     X509* req = NULL;
     EVP_PKEY *pub_key = NULL;
 
-    AssertNotNull(bio = BIO_new_file(csrFile, "rb"));
-    AssertNotNull(d2i_X509_REQ_bio(bio, &req));
+    {
+        AssertNotNull(bio = BIO_new_file(csrFile, "rb"));
+        AssertNotNull(d2i_X509_REQ_bio(bio, &req));
 
-    /*
-     * Extract the public key from the CSR
-     */
-    AssertNotNull(pub_key = X509_REQ_get_pubkey(req));
+        /*
+         * Extract the public key from the CSR
+         */
+        AssertNotNull(pub_key = X509_REQ_get_pubkey(req));
 
-    /*
-     * Verify the signature in the CSR
-     */
-    AssertIntEQ(X509_REQ_verify(req, pub_key), 1);
+        /*
+         * Verify the signature in the CSR
+         */
+        AssertIntEQ(X509_REQ_verify(req, pub_key), 1);
 
-    X509_free(req);
-    BIO_free(bio);
+        X509_free(req);
+        BIO_free(bio);
+    }
+    {
+        AssertNotNull(bio = BIO_new_file(csrPopFile, "rb"));
+        AssertNotNull(d2i_X509_REQ_bio(bio, &req));
+
+        /*
+         * Extract the public key from the CSR
+         */
+        AssertNotNull(pub_key = X509_REQ_get_pubkey(req));
+
+        /*
+         * Verify the signature in the CSR
+         */
+        AssertIntEQ(X509_REQ_verify(req, pub_key), 1);
+
+        /*
+         * Obtain the challenge password from the CSR
+         */
+        AssertIntGE(X509_REQ_get_attr_by_NID(req, NID_pkcs9_challengePassword, -1), 0);
+
+        X509_free(req);
+        BIO_free(bio);
+    }
 }
 
 static void test_wolfSSL_PEM_read_X509(void)

+ 97 - 12
wolfcrypt/src/asn.c

@@ -1660,6 +1660,13 @@ static const byte extExtKeyUsageCodeSigningOid[]  = {43, 6, 1, 5, 5, 7, 3, 3};
 static const byte extExtKeyUsageEmailProtectOid[] = {43, 6, 1, 5, 5, 7, 3, 4};
 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 */
 static const byte pbkdf2Oid[] = {42, 134, 72, 134, 247, 13, 1, 5, 12};
 
@@ -2287,6 +2294,20 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz)
             }
             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:
             break;
@@ -2454,8 +2475,11 @@ int SetObjectId(int len, byte* output)
 {
     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;
 }
@@ -5453,6 +5477,7 @@ static int GetKey(DecodedCert* cert)
         }
     #endif /* NO_DSA */
         default:
+            WOLFSSL_MSG("Unknown or not compiled in key OID");
             return ASN_UNKNOWN_OID_E;
     }
 }
@@ -9480,9 +9505,67 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm)
             }
 
             if (len) {
-                WOLFSSL_MSG("Non-empty attributes. wolfSSL doesn't support "
-                            "parsing CSR attributes.");
-                return ASN_VERSION_E;
+                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;
+                    }
+                    /* For now all supported attributes have the type value
+                     * of ASN_PRINTABLE_STRING or ASN_UTF8STRING but as more
+                     * attributes are supported then this will have to be done
+                     * on a per attribute basis. */
+                    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;
+                    }
+                    switch (oid) {
+                    case CHALLENGE_PASSWORD_OID:
+                        cert->cPwd = (char*)cert->source + cert->srcIdx;
+                        cert->cPwdLen = len;
+                        cert->srcIdx += len;
+                        break;
+                    case SERIAL_NUMBER_OID:
+                        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;
+                    default:
+                        WOLFSSL_MSG("Unsupported attribute type");
+                        return ASN_PARSE_E;
+                    }
+                }
             }
         }
 #endif
@@ -13883,9 +13966,6 @@ int wc_MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz,
 static int SetReqAttrib(byte* output, char* pw, int pwPrintableString,
                         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,
                          0x09, 0x0e };
@@ -13916,8 +13996,11 @@ static int SetReqAttrib(byte* output, char* pw, int pwPrintableString,
             cpStrSz = SetUTF8String(pwSz, cpStr);
         }
         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;
     }
 
     if (extSz) {
@@ -13932,8 +14015,10 @@ static int SetReqAttrib(byte* output, char* pw, int pwPrintableString,
     if (cpSz) {
         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;
         XMEMCPY(&output[sz], cpStr, cpStrSz);

+ 26 - 46
wolfcrypt/src/evp.c

@@ -1330,7 +1330,6 @@ int wolfSSL_EVP_PKEY_CTX_free(WOLFSSL_EVP_PKEY_CTX *ctx)
 WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_ENGINE *e)
 {
     WOLFSSL_EVP_PKEY_CTX* ctx;
-    int type = NID_undef;
 
     if (pkey == NULL) return 0;
     if (e != NULL) return 0;
@@ -1344,15 +1343,8 @@ WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_E
 #if !defined(NO_RSA) && !defined(HAVE_USER_RSA)
     ctx->padding = RSA_PKCS1_PADDING;
 #endif
-    type = wolfSSL_EVP_PKEY_type(pkey->type);
-
-    if (type != NID_undef) {
-        if (wc_LockMutex(&pkey->refMutex) != 0) {
-            WOLFSSL_MSG("Couldn't lock pkey mutex");
-        }
-        pkey->references++;
-
-        wc_UnLockMutex(&pkey->refMutex);
+    if (wolfSSL_EVP_PKEY_up_ref(pkey) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("Couldn't increase key reference count");
     }
     return ctx;
 }
@@ -1925,7 +1917,7 @@ int wolfSSL_EVP_PKEY_copy_parameters(WOLFSSL_EVP_PKEY *to,
 #ifndef NO_DSA
     case EVP_PKEY_DSA:
         if (from->dsa) {
-            WOLFSSL_BIGNUM cpy;
+            WOLFSSL_BIGNUM* cpy;
             if (!to->dsa && !(to->dsa = wolfSSL_DSA_new())) {
                 WOLFSSL_MSG("wolfSSL_DSA_new error");
                 return WOLFSSL_FAILURE;
@@ -1935,12 +1927,12 @@ int wolfSSL_EVP_PKEY_copy_parameters(WOLFSSL_EVP_PKEY *to,
                 return WOLFSSL_FAILURE;
             }
             to->dsa->p = cpy;
-            if (!(cpy = wolfSSL_BN_dup(from->dsa->q)) {
+            if (!(cpy = wolfSSL_BN_dup(from->dsa->q))) {
                 WOLFSSL_MSG("wolfSSL_BN_dup error");
                 return WOLFSSL_FAILURE;
             }
             to->dsa->q = cpy;
-            if (!(cpy = wolfSSL_BN_dup(from->dsa->g)) {
+            if (!(cpy = wolfSSL_BN_dup(from->dsa->g))) {
                 WOLFSSL_MSG("wolfSSL_BN_dup error");
                 return WOLFSSL_FAILURE;
             }
@@ -2375,21 +2367,16 @@ static int wolfSSL_evp_digest_pk_init(WOLFSSL_EVP_MD_CTX *ctx,
 
         ctx->isHMAC = 1;
     }
-    else {
-        int ret;
-
-        if (ctx->pctx == NULL) {
-            ctx->pctx = wolfSSL_EVP_PKEY_CTX_new(pkey, e);
-            if (ctx->pctx == NULL)
-                return WOLFSSL_FAILURE;
-        }
+    else if (wolfSSL_EVP_DigestInit(ctx, type) != 1)
+            return WOLFSSL_FAILURE;
 
-        ret = wolfSSL_EVP_DigestInit(ctx, type);
-        if (ret == WOLFSSL_SUCCESS && pctx != NULL)
-            *pctx = ctx->pctx;
-        return ret;
+    if (ctx->pctx == NULL) {
+        ctx->pctx = wolfSSL_EVP_PKEY_CTX_new(pkey, e);
+        if (ctx->pctx == NULL)
+            return WOLFSSL_FAILURE;
     }
-
+    if (pctx != NULL)
+        *pctx = ctx->pctx;
     return WOLFSSL_SUCCESS;
 }
 
@@ -2399,10 +2386,7 @@ static int wolfSSL_evp_digest_pk_init(WOLFSSL_EVP_MD_CTX *ctx,
 static int wolfssl_evp_digest_pk_update(WOLFSSL_EVP_MD_CTX *ctx,
                                         const void *d, unsigned int cnt)
 {
-    if (ctx->pctx == NULL) {
-        if (!ctx->isHMAC)
-            return WOLFSSL_FAILURE;
-
+    if (ctx->isHMAC) {
         if (wc_HmacUpdate(&ctx->hash.hmac, (const byte *)d, cnt) != 0)
             return WOLFSSL_FAILURE;
 
@@ -2421,12 +2405,9 @@ static int wolfssl_evp_digest_pk_final(WOLFSSL_EVP_MD_CTX *ctx,
 {
     int  ret;
 
-    if (ctx->pctx == NULL) {
+    if (ctx->isHMAC) {
         Hmac hmacCopy;
 
-        if (!ctx->isHMAC)
-            return WOLFSSL_FAILURE;
-
         if (wolfSSL_HmacCopy(&hmacCopy, &ctx->hash.hmac) != WOLFSSL_SUCCESS)
             return WOLFSSL_FAILURE;
         ret = wc_HmacFinal(&hmacCopy, md) == 0;
@@ -2561,10 +2542,7 @@ int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sig,
         return WOLFSSL_FAILURE;
 
     /* Return the maximum size of the signaure when sig is NULL. */
-    if (ctx->pctx == NULL) {
-        if (!ctx->isHMAC)
-            return WOLFSSL_FAILURE;
-
+    if (ctx->isHMAC) {
         hashLen = wolfssl_mac_len(ctx->hash.hmac.macType);
 
         if (sig == NULL) {
@@ -2594,7 +2572,7 @@ int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sig,
     if (wolfssl_evp_digest_pk_final(ctx, digest, &hashLen) <= 0)
         return WOLFSSL_FAILURE;
 
-    if (ctx->pctx == NULL) {
+    if (ctx->isHMAC) {
         /* Copy the HMAC result as signature. */
         if ((unsigned int)(*siglen) > hashLen)
             *siglen = hashLen;
@@ -2679,9 +2657,7 @@ int wolfSSL_EVP_DigestVerifyFinal(WOLFSSL_EVP_MD_CTX *ctx,
     if (ctx == NULL || sig == NULL)
         return WOLFSSL_FAILURE;
 
-    if (ctx->pctx == NULL) {
-        if (!ctx->isHMAC)
-            return WOLFSSL_FAILURE;
+    if (ctx->isHMAC) {
 
         hashLen = wolfssl_mac_len(ctx->hash.hmac.macType);
 
@@ -2693,7 +2669,7 @@ int wolfSSL_EVP_DigestVerifyFinal(WOLFSSL_EVP_MD_CTX *ctx,
     if (wolfssl_evp_digest_pk_final(ctx, digest, &hashLen) <= 0)
         return WOLFSSL_FAILURE;
 
-    if (ctx->pctx == NULL) {
+    if (ctx->isHMAC) {
         /* Check HMAC result matches the signature. */
         if (XMEMCMP(sig, digest, siglen) == 0)
             return WOLFSSL_SUCCESS;
@@ -5766,11 +5742,15 @@ int wolfSSL_EVP_PKEY_set1_RSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_RSA *key)
     if ((pkey == NULL) || (key == NULL))
         return WOLFSSL_FAILURE;
 
+    if (wolfSSL_RSA_up_ref(key) != WOLFSSL_SUCCESS) {
+        WOLFSSL_MSG("wolfSSL_RSA_up_ref failed");
+        return WOLFSSL_FAILURE;
+    }
     if (pkey->rsa != NULL && pkey->ownRsa == 1) {
         wolfSSL_RSA_free(pkey->rsa);
     }
     pkey->rsa    = key;
-    pkey->ownRsa = 0; /* pkey does not own RSA */
+    pkey->ownRsa = 1; /* pkey does not own RSA but needs to call free on it */
     pkey->type   = EVP_PKEY_RSA;
     if (key->inSet == 0) {
         if (SetRsaInternal(key) != WOLFSSL_SUCCESS) {
@@ -6623,10 +6603,10 @@ int wolfSSL_EVP_PKEY_up_ref(WOLFSSL_EVP_PKEY* pkey)
         pkey->references++;
         wc_UnLockMutex(&pkey->refMutex);
 
-        return 1;
+        return WOLFSSL_SUCCESS;
     }
 
-    return 0;
+    return WOLFSSL_FAILURE;
 }
 
 #ifndef NO_RSA

+ 1 - 2
wolfcrypt/src/pkcs7.c

@@ -2269,8 +2269,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd,
 
     byte signingTime[MAX_TIME_STRING_SZ];
 
-    if (pkcs7 == NULL || (pkcs7->contentSz > 0 && pkcs7->content == NULL) ||
-        pkcs7->hashOID == 0 ||
+    if (pkcs7 == NULL || pkcs7->hashOID == 0 ||
         output == NULL || outputSz == NULL || *outputSz == 0 || hashSz == 0 ||
         hashBuf == NULL) {
         return BAD_FUNC_ARG;

+ 3 - 0
wolfssl/internal.h

@@ -2029,6 +2029,8 @@ struct WOLFSSL_CERT_MANAGER {
 #if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
     short           minEccKeySz;         /* minimum allowed ECC key size */
 #endif
+    wolfSSL_Mutex   refMutex;   /* reference count mutex */
+    int             refCount;         /* reference count */
 };
 
 WOLFSSL_LOCAL int CM_SaveCertCache(WOLFSSL_CERT_MANAGER*, const char*);
@@ -3762,6 +3764,7 @@ struct WOLFSSL_X509 {
     byte             serial[EXTERNAL_SERIAL_SIZE];
     char             subjectCN[ASN_NAME_MAX];        /* common name short cut */
 #ifdef WOLFSSL_CERT_REQ
+    WOLFSSL_X509_ATTRIBUTE* challengePwAttr;
     char             challengePw[CTC_NAME_SIZE]; /* for REQ certs */
 #endif
     WOLFSSL_X509_NAME issuer;

+ 3 - 0
wolfssl/openssl/pem.h

@@ -242,6 +242,9 @@ int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh);
 #define PEM_write_ECPrivateKey          wolfSSL_PEM_write_ECPrivateKey
 #define PEM_read_bio_ECPrivateKey       wolfSSL_PEM_read_bio_ECPrivateKey
 #define PEM_read_bio_EC_PUBKEY          wolfSSL_PEM_read_bio_EC_PUBKEY
+#ifndef NO_WOLFSSL_STUB
+#define PEM_write_bio_ECPKParameters(...) 0
+#endif
 /* EVP_KEY */
 #define PEM_read_bio_PrivateKey         wolfSSL_PEM_read_bio_PrivateKey
 #define PEM_read_PUBKEY                 wolfSSL_PEM_read_PUBKEY

+ 6 - 0
wolfssl/openssl/ssl.h

@@ -390,6 +390,7 @@ typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS;
 #define X509_REQ_add1_attr_by_txt       wolfSSL_X509_REQ_add1_attr_by_txt
 #define X509_REQ_get_attr_by_NID        wolfSSL_X509_REQ_get_attr_by_NID
 #define X509_REQ_get_attr               wolfSSL_X509_REQ_get_attr
+#define X509_ATTRIBUTE_get0_type        wolfSSL_X509_ATTRIBUTE_get0_type
 #define X509_to_X509_REQ                wolfSSL_X509_to_X509_REQ
 #define X509_REQ_set_subject_name       wolfSSL_X509_REQ_set_subject_name
 #define X509_REQ_set_pubkey             wolfSSL_X509_REQ_set_pubkey
@@ -654,6 +655,11 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_
 #define BIO_set_write_buffer_size       wolfSSL_BIO_set_write_buffer_size
 #define BIO_f_ssl                       wolfSSL_BIO_f_ssl
 #define BIO_new_socket                  wolfSSL_BIO_new_socket
+#ifndef NO_WOLFSSL_STUB
+#define BIO_new_connect(...)            NULL
+#define BIO_set_conn_port(...)          0
+#define BIO_do_connect(...)             0
+#endif
 #define SSL_set_bio                     wolfSSL_set_bio
 #define BIO_set_ssl                     wolfSSL_BIO_set_ssl
 #define BIO_eof                         wolfSSL_BIO_eof

+ 6 - 1
wolfssl/ssl.h

@@ -334,6 +334,7 @@ struct WOLFSSL_ASN1_TYPE {
 
 struct WOLFSSL_X509_ATTRIBUTE {
     WOLFSSL_ASN1_OBJECT *object;
+    WOLFSSL_ASN1_TYPE *value;
     WOLF_STACK_OF(WOLFSSL_ASN1_TYPE) *set;
 };
 
@@ -2771,6 +2772,7 @@ WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl);
     WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap);
     WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void);
     WOLFSSL_API void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER*);
+    WOLFSSL_API int wolfSSL_CertManager_up_ref(WOLFSSL_CERT_MANAGER*);
 
     WOLFSSL_API int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER*, const char* f,
                                                                  const char* d);
@@ -3603,7 +3605,10 @@ WOLFSSL_API int wolfSSL_X509_REQ_add1_attr_by_txt(WOLFSSL_X509 *req,
                               const unsigned char *bytes, int len);
 WOLFSSL_API WOLFSSL_X509_ATTRIBUTE *wolfSSL_X509_REQ_get_attr(
         const WOLFSSL_X509 *req, int loc);
-
+WOLFSSL_API WOLFSSL_X509_ATTRIBUTE* wolfSSL_X509_ATTRIBUTE_new(void);
+WOLFSSL_API void wolfSSL_X509_ATTRIBUTE_free(WOLFSSL_X509_ATTRIBUTE* attr);
+WOLFSSL_API WOLFSSL_ASN1_TYPE *wolfSSL_X509_ATTRIBUTE_get0_type(
+        WOLFSSL_X509_ATTRIBUTE *attr, int idx);
 WOLFSSL_API WOLFSSL_X509 *wolfSSL_X509_to_X509_REQ(WOLFSSL_X509 *x,
         WOLFSSL_EVP_PKEY *pkey, const WOLFSSL_EVP_MD *md);
 #endif

+ 17 - 0
wolfssl/wolfcrypt/asn.h

@@ -100,6 +100,7 @@ enum ASN_Tags {
     ASN_SEQUENCE          = 0x10,
     ASN_SET               = 0x11,
     ASN_PRINTABLE_STRING  = 0x13,
+    ASN_IA5_STRING        = 0x16,
     ASN_UTC_TIME          = 0x17,
     ASN_OTHER_TYPE        = 0x00,
     ASN_RFC822_TYPE       = 0x01,
@@ -427,6 +428,7 @@ enum Oid_Types {
     oidCertNameType     = 17,
     oidTlsExtType       = 18,
     oidCrlExtType       = 19,
+    oidCsrAttrType      = 20,
     oidIgnoreType
 };
 
@@ -593,6 +595,13 @@ enum KeyIdType {
 };
 #endif
 
+#ifdef WOLFSSL_CERT_REQ
+enum CsrAttyType {
+    CHALLENGE_PASSWORD_OID = 659,
+    SERIAL_NUMBER_OID = 94,
+};
+#endif
+
 /* Key usage extension bits (based on RFC 5280) */
 #define KEYUSE_DIGITAL_SIG    0x0080
 #define KEYUSE_CONTENT_COMMIT 0x0040
@@ -894,6 +903,14 @@ struct DecodedCert {
     int     extCertPoliciesNb;
 #endif /* defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_EXT) */
 
+#ifdef WOLFSSL_CERT_REQ
+    /* CSR attributes */
+    char*   cPwd; /* challengePassword */
+    int     cPwdLen;
+    char*   sNum; /* Serial Number */
+    int     sNumLen;
+#endif /* WOLFSSL_CERT_REQ */
+
     Signer* ca;
 #ifndef NO_CERTS
     SignatureCtx sigCtx;