static int GetKey(DecodedCert* cert)
{
    int length;
#ifndef NO_DSA
    int tmpLen;
#endif
#if defined(HAVE_ECC) || defined(HAVE_NTRU) || !defined(NO_DSA)
    int tmpIdx = cert->srcIdx;
#endif

    if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0)
        return ASN_PARSE_E;

#ifndef NO_DSA
    tmpLen = length + 4;
#endif

    if (GetAlgoId(cert->source, &cert->srcIdx,
                  &cert->keyOID, oidKeyType, cert->maxIdx) < 0)
        return ASN_PARSE_E;

    switch (cert->keyOID) {
   #ifndef NO_RSA
        case RSAk:
        {
            int ret;

            ret = CheckBitString(cert->source, &cert->srcIdx, &length,
                                 cert->maxIdx, 1, NULL);
            if (ret != 0)
                return ret;

            #ifdef HAVE_OCSP
                ret = CalcHashId(cert->source + cert->srcIdx, length,
                        cert->subjectKeyHash);
                if (ret != 0)
                    return ret;
            #endif

            return StoreRsaKey(cert, cert->srcIdx + length);
        }

    #endif /* NO_RSA */
    #ifdef HAVE_NTRU
        case NTRUk:
        {
            const byte* key = &cert->source[tmpIdx];
            byte*       next = (byte*)key;
            word16      keyLen;
            word32      rc;
            word32      remaining = cert->maxIdx - cert->srcIdx;
            byte*       publicKey;
#ifdef WOLFSSL_SMALL_STACK
            byte*       keyBlob = NULL;
#else
            byte        keyBlob[MAX_NTRU_KEY_SZ];
#endif
            rc = ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(key,
                                &keyLen, NULL, &next, &remaining);
            if (rc != NTRU_OK)
                return ASN_NTRU_KEY_E;
            if (keyLen > MAX_NTRU_KEY_SZ)
                return ASN_NTRU_KEY_E;

#ifdef WOLFSSL_SMALL_STACK
            keyBlob = (byte*)XMALLOC(MAX_NTRU_KEY_SZ, cert->heap,
                                     DYNAMIC_TYPE_TMP_BUFFER);
            if (keyBlob == NULL)
                return MEMORY_E;
#endif

            rc = ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(key,
                                &keyLen, keyBlob, &next, &remaining);
            if (rc != NTRU_OK) {
#ifdef WOLFSSL_SMALL_STACK
                XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
                return ASN_NTRU_KEY_E;
            }

            if ( (next - key) < 0) {
#ifdef WOLFSSL_SMALL_STACK
                XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
                return ASN_NTRU_KEY_E;
            }

            cert->srcIdx = tmpIdx + (int)(next - key);

            publicKey = (byte*)XMALLOC(keyLen, cert->heap,
                                       DYNAMIC_TYPE_PUBLIC_KEY);
            if (publicKey == NULL) {
#ifdef WOLFSSL_SMALL_STACK
                XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif
                return MEMORY_E;
            }
            XMEMCPY(publicKey, keyBlob, keyLen);
            cert->publicKey = publicKey;
            cert->pubKeyStored = 1;
            cert->pubKeySize   = keyLen;

#ifdef WOLFSSL_SMALL_STACK
            XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
#endif

            return 0;
        }
    #endif /* HAVE_NTRU */
    #ifdef HAVE_ECC
        case ECDSAk:
        {
            int ret;
            byte seq[5];
            int pubLen = length + 1 + SetLength(length, seq);
            word32 localIdx;
            byte* publicKey;
            byte  tag;

            localIdx = cert->srcIdx;
            if (GetASNTag(cert->source, &localIdx, &tag, cert->maxIdx) < 0)
                return ASN_PARSE_E;

            if (tag != (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
                if (GetObjectId(cert->source, &cert->srcIdx,
                            &cert->pkCurveOID, oidCurveType, cert->maxIdx) < 0)
                    return ASN_PARSE_E;

                if (CheckCurve(cert->pkCurveOID) < 0)
                    return ECC_CURVE_OID_E;

                /* key header */
                ret = CheckBitString(cert->source, &cert->srcIdx, &length,
                                                         cert->maxIdx, 1, NULL);
                if (ret != 0)
                    return ret;
            #ifdef HAVE_OCSP
                ret = CalcHashId(cert->source + cert->srcIdx, length,
                        cert->subjectKeyHash);
                if (ret != 0)
                    return ret;
            #endif
            }

            publicKey = (byte*)XMALLOC(pubLen, cert->heap,
                                       DYNAMIC_TYPE_PUBLIC_KEY);
            if (publicKey == NULL)
                return MEMORY_E;
            XMEMCPY(publicKey, &cert->source[tmpIdx], pubLen);
            cert->publicKey = publicKey;
            cert->pubKeyStored = 1;
            cert->pubKeySize   = pubLen;

            cert->srcIdx = tmpIdx + pubLen;

            return 0;
        }
    #endif /* HAVE_ECC */
    #ifdef HAVE_ED25519
        case ED25519k:
        {
            byte* publicKey;
            int ret;

            cert->pkCurveOID = ED25519k;

            ret = CheckBitString(cert->source, &cert->srcIdx, &length,
                                 cert->maxIdx, 1, NULL);
            if (ret != 0)
                return ret;

            #ifdef HAVE_OCSP
                ret = CalcHashId(cert->source + cert->srcIdx, length,
                        cert->subjectKeyHash);
                if (ret != 0)
                    return ret;
            #endif

            publicKey = (byte*) XMALLOC(length, cert->heap,
                                        DYNAMIC_TYPE_PUBLIC_KEY);
            if (publicKey == NULL)
                return MEMORY_E;
            XMEMCPY(publicKey, &cert->source[cert->srcIdx], length);
            cert->publicKey = publicKey;
            cert->pubKeyStored = 1;
            cert->pubKeySize   = length;

            cert->srcIdx += length;

            return 0;
        }
    #endif /* HAVE_ED25519 */
    #ifdef HAVE_ED448
        case ED448k:
        {
            byte* publicKey;
            int ret;

            cert->pkCurveOID = ED448k;

            ret = CheckBitString(cert->source, &cert->srcIdx, &length,
                                 cert->maxIdx, 1, NULL);
            if (ret != 0)
                return ret;

            #ifdef HAVE_OCSP
                ret = CalcHashId(cert->source + cert->srcIdx, length,
                                 cert->subjectKeyHash);
                if (ret != 0)
                    return ret;
            #endif

            publicKey = (byte*) XMALLOC(length, cert->heap,
                                        DYNAMIC_TYPE_PUBLIC_KEY);
            if (publicKey == NULL)
                return MEMORY_E;
            XMEMCPY(publicKey, &cert->source[cert->srcIdx], length);
            cert->publicKey = publicKey;
            cert->pubKeyStored = 1;
            cert->pubKeySize   = length;

            cert->srcIdx += length;

            return 0;
        }
    #endif /* HAVE_ED448 */
    #ifndef NO_DSA
        case DSAk:
        {
            int ret;
            ret = GetSequence(cert->source, &cert->srcIdx, &length,
                           cert->maxIdx);
            if (ret < 0)
                return ret;

            ret = SkipInt(cert->source, &cert->srcIdx, cert->maxIdx);
            if (ret != 0)
                return ret;
            ret = SkipInt(cert->source, &cert->srcIdx, cert->maxIdx);
            if (ret != 0)
                return ret;
            ret = SkipInt(cert->source, &cert->srcIdx, cert->maxIdx);
            if (ret != 0)
                return ret;

            ret = CheckBitString(cert->source, &cert->srcIdx, &length,
                                                         cert->maxIdx, 1, NULL);
            if (ret != 0)
                return ret;

            ret = GetASNInt(cert->source, &cert->srcIdx, &length, cert->maxIdx);
            if (ret !=0)
                return ASN_PARSE_E;

            cert->publicKey = cert->source + tmpIdx;
            cert->pubKeySize = tmpLen;
            cert->srcIdx += length;
            return 0;
        }
    #endif /* NO_DSA */
        default:
            WOLFSSL_MSG("Unknown or not compiled in key OID");
            return ASN_UNKNOWN_OID_E;
    }
}