Index: azure_iot_hub_f767zi/trunk/wolfssl-4.7.0/src/ocsp.c
===================================================================
--- azure_iot_hub_f767zi/trunk/wolfssl-4.4.0/src/ocsp.c	(revision 457)
+++ azure_iot_hub_f767zi/trunk/wolfssl-4.7.0/src/ocsp.c	(revision 464)
@@ -76,4 +76,7 @@
     CertStatus *status, *next;
 
+    if (entry == NULL)
+        return;
+
     WOLFSSL_ENTER("FreeOcspEntry");
 
@@ -83,4 +86,14 @@
         if (status->rawOcspResponse)
             XFREE(status->rawOcspResponse, heap, DYNAMIC_TYPE_OCSP_STATUS);
+
+#ifdef OPENSSL_EXTRA
+        if (status->serialInt) {
+            if (status->serialInt->isDynamic) {
+                XFREE(status->serialInt->data, NULL, DYNAMIC_TYPE_OPENSSL);
+            }
+            XFREE(status->serialInt, NULL, DYNAMIC_TYPE_OPENSSL);
+        }
+        status->serialInt = NULL;
+#endif
 
         XFREE(status, heap, DYNAMIC_TYPE_OCSP_STATUS);
@@ -273,7 +286,9 @@
 #ifdef WOLFSSL_SMALL_STACK
     CertStatus*   newStatus;
+    OcspEntry*    newSingle;
     OcspResponse* ocspResponse;
 #else
     CertStatus    newStatus[1];
+    OcspEntry     newSingle[1];
     OcspResponse  ocspResponse[1];
 #endif
@@ -283,11 +298,14 @@
 #ifdef WOLFSSL_SMALL_STACK
     newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
+                                                       DYNAMIC_TYPE_OCSP_STATUS);
+    newSingle = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL,
+                                                       DYNAMIC_TYPE_OCSP_ENTRY);
     ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-
-    if (newStatus == NULL || ocspResponse == NULL) {
-        if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+                                                       DYNAMIC_TYPE_OCSP_REQUEST);
+
+    if (newStatus == NULL || newSingle == NULL || ocspResponse == NULL) {
+        if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_OCSP_STATUS);
+        if (newSingle) XFREE(newSingle, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
+        if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
 
         WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR);
@@ -295,7 +313,7 @@
     }
 #endif
-    XMEMSET(newStatus, 0, sizeof(CertStatus));
-
-    InitOcspResponse(ocspResponse, newStatus, response, responseSz);
+    InitOcspResponse(ocspResponse, newSingle, newStatus, response, responseSz,
+                     ocsp->cm->heap);
+
     ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0);
     if (ret != 0) {
@@ -326,5 +344,5 @@
     }
 
-    ret = xstat2err(ocspResponse->status->status);
+    ret = xstat2err(ocspResponse->single->status->status);
     if (ret == 0) {
         validated = 1;
@@ -343,6 +361,6 @@
 
         /* Replace existing certificate entry with updated */
-        newStatus->next = status->next;
-        XMEMCPY(status, newStatus, sizeof(CertStatus));
+        newSingle->status->next = status->next;
+        XMEMCPY(status, newSingle->status, sizeof(CertStatus));
     }
     else {
@@ -351,5 +369,5 @@
                                       ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS);
         if (status != NULL) {
-            XMEMCPY(status, newStatus, sizeof(CertStatus));
+            XMEMCPY(status, newSingle->status, sizeof(CertStatus));
             status->next  = entry->status;
             entry->status = status;
@@ -380,6 +398,7 @@
 
 #ifdef WOLFSSL_SMALL_STACK
-    XFREE(newStatus,    NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    XFREE(newStatus,    NULL, DYNAMIC_TYPE_OCSP_STATUS);
+    XFREE(newSingle,    NULL, DYNAMIC_TYPE_OCSP_ENTRY);
+    XFREE(ocspResponse, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
 #endif
     return ret;
@@ -454,4 +473,5 @@
     else {
         /* cert doesn't have extAuthInfo, assuming CERT_GOOD */
+        WOLFSSL_MSG("Cert has no OCSP URL, assuming CERT_GOOD");
         return 0;
     }
@@ -493,5 +513,5 @@
 
 #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \
-    defined(WOLFSSL_APACHE_HTTPD)
+    defined(WOLFSSL_APACHE_HTTPD) || defined(HAVE_LIGHTY)
 
 int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs,
@@ -500,19 +520,30 @@
     WOLFSSL_ASN1_TIME** nextupd)
 {
+    WOLFSSL_OCSP_SINGLERESP* single;
+
     if (bs == NULL || id == NULL)
         return WOLFSSL_FAILURE;
 
-    /* Only supporting one certificate status in asn.c. */
-    if (CompareOcspReqResp(id, bs) != 0)
+    single = bs->single;
+    while (single != NULL) {
+        if ((XMEMCMP(single->status->serial, id->status->serial, single->status->serialSz) == 0)
+         && (XMEMCMP(single->issuerHash, id->issuerHash, OCSP_DIGEST_SIZE) == 0)
+         && (XMEMCMP(single->issuerKeyHash, id->issuerKeyHash, OCSP_DIGEST_SIZE) == 0)) {
+            break;
+        }
+        single = single->next;
+    }
+
+    if (single == NULL)
         return WOLFSSL_FAILURE;
 
     if (status != NULL)
-        *status = bs->status->status;
+        *status = single->status->status;
     if (thisupd != NULL)
-        *thisupd = &bs->status->thisDateParsed;
+        *thisupd = &single->status->thisDateParsed;
     if (nextupd != NULL)
-        *nextupd = &bs->status->nextDateParsed;
-
-    /* TODO: Not needed for Nginx. */
+        *nextupd = &single->status->nextDateParsed;
+
+    /* TODO: Not needed for Nginx or httpd */
     if (reason != NULL)
         *reason = 0;
@@ -550,5 +581,5 @@
 void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId)
 {
-    FreeOcspRequest(certId);
+    FreeOcspEntry(certId, NULL);
     XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
 }
@@ -559,4 +590,5 @@
 {
     WOLFSSL_OCSP_CERTID* certId;
+    CertStatus* certStatus;
     DecodedCert cert;
     WOLFSSL_CERT_MANAGER* cm;
@@ -581,20 +613,34 @@
     certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL,
                                            DYNAMIC_TYPE_OPENSSL);
-    if (certId != NULL) {
-        InitDecodedCert(&cert, subject->derCert->buffer,
-                        subject->derCert->length, NULL);
-        if (ParseCertRelative(&cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) {
+    certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
+                                           DYNAMIC_TYPE_OPENSSL);
+
+    if (certId == NULL || certStatus == NULL) {
+        if (certId)
             XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
-            certId = NULL;
-        }
-        else {
-            ret = InitOcspRequest(certId, &cert, 0, NULL);
-            if (ret != 0) {
-                XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
-                certId = NULL;
-            }
-        }
-        FreeDecodedCert(&cert);
-    }
+        if (certStatus)
+            XFREE(certStatus, NULL, DYNAMIC_TYPE_OPENSSL);
+
+        return NULL;
+    }
+
+    XMEMSET(certId, 0, sizeof(WOLFSSL_OCSP_CERTID));
+    XMEMSET(certStatus, 0, sizeof(CertStatus));
+
+    certId->status = certStatus;
+
+    InitDecodedCert(&cert, subject->derCert->buffer,
+                    subject->derCert->length, NULL);
+    if (ParseCertRelative(&cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) {
+        XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL);
+        certId = NULL;
+    }
+    else {
+        XMEMCPY(certId->issuerHash, cert.issuerHash, OCSP_DIGEST_SIZE);
+        XMEMCPY(certId->issuerKeyHash, cert.issuerKeyHash, OCSP_DIGEST_SIZE);
+        XMEMCPY(certId->status->serial, cert.serial, cert.serialSz);
+        certId->status->serialSz = cert.serialSz;
+    }
+    FreeDecodedCert(&cert);
 
     wolfSSL_CertManagerFree(cm);
@@ -636,11 +682,19 @@
 void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response)
 {
-    if (response->status != NULL)
-        XFREE(response->status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (response == NULL)
+        return;
+
+    if (response->single != NULL) {
+        FreeOcspEntry(response->single, NULL);
+        XFREE(response->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
+    }
+
     if (response->source != NULL)
         XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL);
-}
-
+
+    XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
+}
+
+#ifndef NO_BIO
 OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio,
     OcspResponse** response)
@@ -707,4 +761,5 @@
     return ret;
 }
+#endif /* !NO_BIO */
 
 OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response,
@@ -722,5 +777,5 @@
     if (resp == NULL) {
         resp = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL,
-                                      DYNAMIC_TYPE_OPENSSL);
+                                      DYNAMIC_TYPE_OCSP_REQUEST);
         if (resp == NULL)
             return NULL;
@@ -730,14 +785,24 @@
     resp->source = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER);
     if (resp->source == NULL) {
-        XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL);
+        XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
         return NULL;
     }
-    resp->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
-                                                       DYNAMIC_TYPE_TMP_BUFFER);
-    if (resp->status == NULL) {
+    resp->single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL,
+                                      DYNAMIC_TYPE_OCSP_ENTRY);
+    if (resp->single == NULL) {
         XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-        XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL);
+        XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
         return NULL;
     }
+    XMEMSET(resp->single, 0, sizeof(OcspEntry));
+    resp->single->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
+                                      DYNAMIC_TYPE_OCSP_STATUS);
+    if (resp->single->status == NULL) {
+        XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+        XFREE(resp, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
+        XFREE(resp->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
+        return NULL;
+    }
+    XMEMSET(resp->single->status, 0, sizeof(CertStatus));
 
     XMEMCPY(resp->source, *data, len);
@@ -795,14 +860,14 @@
 
     bs = (WOLFSSL_OCSP_BASICRESP*)XMALLOC(sizeof(WOLFSSL_OCSP_BASICRESP), NULL,
-                                          DYNAMIC_TYPE_OPENSSL);
+                                          DYNAMIC_TYPE_OCSP_REQUEST);
     if (bs == NULL)
         return NULL;
 
     XMEMCPY(bs, response, sizeof(OcspResponse));
-    bs->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL,
-                                      DYNAMIC_TYPE_TMP_BUFFER);
+    bs->single = (OcspEntry*)XMALLOC(sizeof(OcspEntry), NULL,
+                                    DYNAMIC_TYPE_OCSP_ENTRY);
     bs->source = (byte*)XMALLOC(bs->maxIdx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
-    if (bs->status == NULL || bs->source == NULL) {
-        if (bs->status) XFREE(bs->status, NULL, DYNAMIC_TYPE_TMP_BUFFER);
+    if (bs->single == NULL || bs->source == NULL) {
+        if (bs->single) XFREE(bs->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
         if (bs->source) XFREE(bs->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
         wolfSSL_OCSP_RESPONSE_free(bs);
@@ -810,5 +875,5 @@
     }
     else {
-        XMEMCPY(bs->status, response->status, sizeof(CertStatus));
+        XMEMCPY(bs->single, response->single, sizeof(OcspEntry));
         XMEMCPY(bs->source, response->source, response->maxIdx);
     }
@@ -851,21 +916,8 @@
         return NULL;
 
-    FreeOcspRequest(req);
-    XMEMCPY(req, cid, sizeof(OcspRequest));
-
-    if (cid->serial != NULL) {
-        req->serial = (byte*)XMALLOC(cid->serialSz, NULL,
-                                     DYNAMIC_TYPE_OCSP_REQUEST);
-        req->url = (byte*)XMALLOC(cid->urlSz, NULL, DYNAMIC_TYPE_OCSP_REQUEST);
-        if (req->serial == NULL || req->url == NULL) {
-            FreeOcspRequest(req);
-            return NULL;
-        }
-
-        XMEMCPY(req->serial, cid->serial, cid->serialSz);
-        XMEMCPY(req->url, cid->url, cid->urlSz);
-    }
-
-    wolfSSL_OCSP_REQUEST_free(cid);
+    XMEMCPY(req->issuerHash, cid->issuerHash, KEYID_SIZE);
+    XMEMCPY(req->issuerKeyHash, cid->issuerKeyHash, KEYID_SIZE);
+    XMEMCPY(req->serial, cid->status->serial, cid->status->serialSz);
+    req->serialSz = cid->status->serialSz;
 
     return req;
@@ -876,10 +928,9 @@
     WOLFSSL_OCSP_CERTID* certId;
 
-    if (id == NULL) {
+    if (id == NULL)
         return NULL;
-    }
 
     certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID),
-        id->heap, DYNAMIC_TYPE_OPENSSL);
+        NULL, DYNAMIC_TYPE_OPENSSL);
     if (certId) {
         XMEMCPY(certId, id, sizeof(WOLFSSL_OCSP_CERTID));
@@ -890,4 +941,5 @@
 
 #if defined(OPENSSL_ALL) || defined(APACHE_HTTPD)
+#ifndef NO_BIO
 int wolfSSL_i2d_OCSP_REQUEST_bio(WOLFSSL_BIO* out,
         WOLFSSL_OCSP_REQUEST *req)
@@ -923,4 +975,89 @@
     return WOLFSSL_FAILURE;
 }
+#endif /* !NO_BIO */
+
+int wolfSSL_i2d_OCSP_CERTID(WOLFSSL_OCSP_CERTID* id, unsigned char** data)
+{
+    if (id == NULL || data == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (*data != NULL) {
+        XMEMCPY(*data, id->rawCertId, id->rawCertIdSize);
+        *data = *data + id->rawCertIdSize;
+    }
+    else {
+        *data = (unsigned char*)XMALLOC(id->rawCertIdSize, NULL, DYNAMIC_TYPE_OPENSSL);
+        if (*data == NULL) {
+            return WOLFSSL_FAILURE;
+        }
+        XMEMCPY(*data, id->rawCertId, id->rawCertIdSize);
+    }
+
+    return id->rawCertIdSize;
+}
+
+const WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_SINGLERESP_get0_id(const WOLFSSL_OCSP_SINGLERESP *single)
+{
+    return single;
+}
+
+int wolfSSL_OCSP_single_get0_status(WOLFSSL_OCSP_SINGLERESP *single,
+                                    int *reason,
+                                    WOLFSSL_ASN1_TIME **revtime,
+                                    WOLFSSL_ASN1_TIME **thisupd,
+                                    WOLFSSL_ASN1_TIME **nextupd)
+{
+    if (single == NULL)
+        return WOLFSSL_FAILURE;
+
+    if (thisupd != NULL)
+        *thisupd = &single->status->thisDateParsed;
+    if (nextupd != NULL)
+        *nextupd = &single->status->nextDateParsed;
+
+    if (reason != NULL)
+        *reason = 0;
+    if (revtime != NULL)
+        *revtime = NULL;
+
+    return single->status->status;
+}
+
+int wolfSSL_OCSP_resp_count(WOLFSSL_OCSP_BASICRESP *bs)
+{
+    WOLFSSL_OCSP_SINGLERESP* single;
+    int count = 0;
+
+    if (bs == NULL)
+        return WOLFSSL_FAILURE;
+
+    single = bs->single;
+    while(single != NULL)
+    {
+        ++count;
+        single = single->next;
+    }
+
+    return count;
+}
+
+WOLFSSL_OCSP_SINGLERESP* wolfSSL_OCSP_resp_get0(WOLFSSL_OCSP_BASICRESP *bs, int idx)
+{
+    WOLFSSL_OCSP_SINGLERESP* single;
+    int currIdx = 0;
+
+    if (bs == NULL)
+        return NULL;
+
+    single = bs->single;
+    while(single != NULL && currIdx != idx)
+    {
+        single = single->next;
+        ++currIdx;
+    }
+
+    return single;
+}
+
 #endif /* OPENSSL_ALL || APACHE_HTTPD */
 
@@ -980,7 +1117,7 @@
             return 0;
 
-        if (cid->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) {
+        if (cid->status->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) {
             /* allocate data buffer, +2 for type and length */
-            ser->data = (unsigned char*)XMALLOC(cid->serialSz + 2, NULL,
+            ser->data = (unsigned char*)XMALLOC(cid->status->serialSz + 2, NULL,
                 DYNAMIC_TYPE_OPENSSL);
             if (ser->data == NULL) {
@@ -988,5 +1125,5 @@
                 return 0;
             }
-            ser->dataMax = cid->serialSz + 2;
+            ser->dataMax = cid->status->serialSz + 2;
             ser->isDynamic = 1;
         } else {
@@ -998,14 +1135,14 @@
         #ifdef WOLFSSL_QT
             /* Serial number starts at 0 index of ser->data */
-            XMEMCPY(&ser->data[i], cid->serial, cid->serialSz);
-            ser->length = cid->serialSz;
+            XMEMCPY(&ser->data[i], cid->status->serial, cid->status->serialSz);
+            ser->length = cid->status->serialSz;
         #else
             ser->data[i++] = ASN_INTEGER;
-            i += SetLength(cid->serialSz, ser->data + i);
-            XMEMCPY(&ser->data[i], cid->serial, cid->serialSz);
+            i += SetLength(cid->status->serialSz, ser->data + i);
+            XMEMCPY(&ser->data[i], cid->status->serial, cid->status->serialSz);
         #endif
 
-        cid->serialInt = ser;
-        *serial = cid->serialInt;
+        cid->status->serialInt = ser;
+        *serial = ser;
     }
 
