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;

    WOLFSSL_ENTER("DecodeSingleResponse");

    prevIndex = idx;

    /* Wrapper around the Single Response */
    if (GetSequence(source, &idx, &length, size) < 0)
        return ASN_PARSE_E;

    /* Wrapper around the CertID */
    certIdIdx = idx;
    if (GetSequence(source, &idx, &length, 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;
    if (length > (int)sizeof(single->issuerHash))
        return BUFFER_E;
    XMEMCPY(single->issuerHash, source + idx, length);
    idx += length;
    /* Save reference to the hash of the issuer public key */
    ret = GetOctetString(source, &idx, &length, size);
    if (ret < 0)
        return ret;
    if (length > (int)sizeof(single->issuerKeyHash))
        return BUFFER_E;
    XMEMCPY(single->issuerKeyHash, source + idx, length);
    idx += length;

    /* Get serial number */
    if (GetSerialNumber(source, &idx, single->status->serial, &single->status->serialSz, size) < 0)
        return ASN_PARSE_E;
    single->rawCertIdSize = idx - certIdIdx;

    if (idx >= size)
        return BUFFER_E;

    /* CertStatus */
    switch (source[idx++])
    {
        case (ASN_CONTEXT_SPECIFIC | CERT_GOOD):
            single->status->status = CERT_GOOD;
            idx++;
            break;
        case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_REVOKED):
            single->status->status = CERT_REVOKED;
            if (GetLength(source, &idx, &length, size) < 0)
                return ASN_PARSE_E;
            idx += length;
            break;
        case (ASN_CONTEXT_SPECIFIC | CERT_UNKNOWN):
            single->status->status = CERT_UNKNOWN;
            idx++;
            break;
        default:
            return ASN_PARSE_E;
    }

#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
    single->status->thisDateAsn = source + idx;
    localIdx = 0;
    if (GetDateInfo(single->status->thisDateAsn, &localIdx, NULL,
                    (byte*)&single->status->thisDateParsed.type,
                    &single->status->thisDateParsed.length, size) < 0)
        return ASN_PARSE_E;
    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(single->status->thisDate, single->status->thisDateFormat, BEFORE))
        return ASN_BEFORE_DATE_E;
#endif
#endif

    /* 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) &&
        GetASNTag(source, &localIdx, &tag, size) == 0 &&
        tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
    {
        idx++;
        if (GetLength(source, &idx, &length, size) < 0)
            return ASN_PARSE_E;
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
        single->status->nextDateAsn = source + idx;
        localIdx = 0;
        if (GetDateInfo(single->status->nextDateAsn, &localIdx, NULL,
                        (byte*)&single->status->nextDateParsed.type,
                        &single->status->nextDateParsed.length, size) < 0)
            return ASN_PARSE_E;
        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(single->status->nextDate, single->status->nextDateFormat, AFTER))
            return ASN_AFTER_DATE_E;
#endif
#endif
    }

    /* Skip the optional extensions in singleResponse. */
    localIdx = idx;
    if (((int)(idx - prevIndex) < wrapperSz) &&
        GetASNTag(source, &localIdx, &tag, size) == 0 &&
        tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
    {
        idx++;
        if (GetLength(source, &idx, &length, size) < 0)
            return ASN_PARSE_E;
        idx += length;
    }

    *ioIndex = idx;

    return 0;
}
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;

    WOLFSSL_ENTER("DecodeSingleResponse");

    prevIndex = idx;

     
    if (GetSequence(source, &idx, &length, size) < 0)
        return ASN_PARSE_E;

     
    certIdIdx = idx;
    if (GetSequence(source, &idx, &length, size) < 0)
        return ASN_PARSE_E;
    single->rawCertId = source + certIdIdx;
     
    ret = GetAlgoId(source, &idx, &oid, oidIgnoreType, size);
    if (ret < 0)
        return ret;
    single->hashAlgoOID = oid;
     
    ret = GetOctetString(source, &idx, &length, size);
    if (ret < 0)
        return ret;
    if (length > (int)sizeof(single->issuerHash))
        return BUFFER_E;
    XMEMCPY(single->issuerHash, source + idx, length);
    idx += length;
     
    ret = GetOctetString(source, &idx, &length, size);
    if (ret < 0)
        return ret;
    if (length > (int)sizeof(single->issuerKeyHash))
        return BUFFER_E;
    XMEMCPY(single->issuerKeyHash, source + idx, length);
    idx += length;

     
    if (GetSerialNumber(source, &idx, single->status->serial, &single->status->serialSz, size) < 0)
        return ASN_PARSE_E;
    single->rawCertIdSize = idx - certIdIdx;

    if (idx >= size)
        return BUFFER_E;

     
    switch (source[idx++])
    {
        case (ASN_CONTEXT_SPECIFIC | CERT_GOOD):
            single->status->status = CERT_GOOD;
            idx++;
            break;
        case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_REVOKED):
            single->status->status = CERT_REVOKED;
            if (GetLength(source, &idx, &length, size) < 0)
                return ASN_PARSE_E;
            idx += length;
            break;
        case (ASN_CONTEXT_SPECIFIC | CERT_UNKNOWN):
            single->status->status = CERT_UNKNOWN;
            idx++;
            break;
        default:
            return ASN_PARSE_E;
    }

#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
    single->status->thisDateAsn = source + idx;
    localIdx = 0;
    if (GetDateInfo(single->status->thisDateAsn, &localIdx, NULL,
                    (byte*)&single->status->thisDateParsed.type,
                    &single->status->thisDateParsed.length, size) < 0)
        return ASN_PARSE_E;
    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(single->status->thisDate, single->status->thisDateFormat, BEFORE))
        return ASN_BEFORE_DATE_E;
#endif
#endif

     
    localIdx = idx;
    if (((int)(idx - prevIndex) < wrapperSz) &&
        GetASNTag(source, &localIdx, &tag, size) == 0 &&
        tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
    {
        idx++;
        if (GetLength(source, &idx, &length, size) < 0)
            return ASN_PARSE_E;
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
        single->status->nextDateAsn = source + idx;
        localIdx = 0;
        if (GetDateInfo(single->status->nextDateAsn, &localIdx, NULL,
                        (byte*)&single->status->nextDateParsed.type,
                        &single->status->nextDateParsed.length, size) < 0)
            return ASN_PARSE_E;
        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(single->status->nextDate, single->status->nextDateFormat, AFTER))
            return ASN_AFTER_DATE_E;
#endif
#endif
    }

     
    localIdx = idx;
    if (((int)(idx - prevIndex) < wrapperSz) &&
        GetASNTag(source, &localIdx, &tag, size) == 0 &&
        tag == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
    {
        idx++;
        if (GetLength(source, &idx, &length, size) < 0)
            return ASN_PARSE_E;
        idx += length;
    }

    *ioIndex = idx;

    return 0;
}